scripts/xldd.in
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Nov 23 21:34:56 2010 +0100 (2010-11-23)
changeset 2184 e826624966a1
parent 2183 dbecd99ecba5
child 2186 78d2f99d403f
permissions -rwxr-xr-x
scripts/xldd: fix version string

The version string was hard-coded.
Now, the version string follows the crosstool-NG version.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
     1 #!@@CT_bash@@
     2 
     3 # NON-CONFIGURABLE STUFF!
     4 export LC_ALL=C
     5 version="@@CT_VERSION@@"
     6 sed="@@CT_sed@@"
     7 grep="@@CT_grep@@"
     8 my_name="$( basename "${0}" )"
     9 prefix="${0%-ldd}"
    10 gcc="${prefix}-gcc"
    11 readelf="${prefix}-readelf"
    12 fake_load_addr="$((0xdeadbeef))"
    13 fake_load_addr_sys="$((0x8badf00d))"
    14 ld_library_path="/lib:/usr/lib"
    15 
    16 do_error() {
    17     printf "%s: %s\n" "${my_name}" "$*" >&2
    18 }
    19 
    20 do_opt_error() {
    21     do_error "$@"
    22     printf "Try \`%s --help' for more information\n" >&2
    23 }
    24 
    25 show_version() {
    26     # Fake a real ldd, just in case some dumb script would check
    27     cat <<_EOF_
    28 ldd (crosstool-NG) ${version}
    29 Copyright (C) 2010 "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
    30 This is free software; see the source for copying conditions.  There is NO
    31 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    32 Licensed under the GPLv2, see the file LICENSES in the top-directory of the
    33 sources for this package.
    34 _EOF_
    35 }
    36 
    37 show_help() {
    38     cat <<_EOF_
    39 Usage: ${my_name} [OPTION]... --root DIR FILE...
    40       --help              print this help and exit
    41       --version           print version information and exit
    42       --root dir          treat dir as being the root of the target
    43   -s, --show-system       mark libs from the sysroot with a trailing '[*]'
    44 
    45 _EOF_
    46     cat <<_EOF_ |fmt
    47 ${my_name} tries to mimick the behavior of a real native ldd, but can be
    48 used in a cross-development environment. Here is how it differs from a
    49 real native ldd:
    50 
    51 The LD_LIBRARY_PATH variable is not used, as it can not reliably be
    52 guessed except at runtime, and we can't run.
    53 
    54 ${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf
    55 (it understands the include directives therein for libces that have that).
    56 [Note: this is missing for now...]
    57 
    58 ${my_name} will search the directory specified with --root for libraries
    59 to resolve the NEEDED tags. If --root is not set, then ${my_name} will
    60 use the value in the environment variable \${CT_XLDD_ROOT}. If neither
    61 is set, then this is an error.
    62 
    63 If NEEDED libraries can't be found in the specified root directory, then
    64 ${my_name} will also look in the sysroot of the toolchain to see if it
    65 can find them.
    66 
    67 For NEEDED libraries that were found, the output will look like:
    68         libneeded.so => /path/to/libneeded.so (0xloadaddr)
    69 
    70 and for those that were not found, the output will look like:
    71         libneeded.so not found
    72 
    73 The paths are relative to the specified root directory, or to the sysroot
    74 (eg. /lib/libneeded.so, /usr/lib/libneeded.so, and so on...).
    75 
    76 The expected load address 'loadaddr' is a faked address to match the output
    77 of the real ldd, but has no actual meaning (set to some constants for now,
    78 0x8badf00d for libraries from the sysroot, 0xdeadbeef for others).
    79 _EOF_
    80 
    81 # Unimplemeted yet:
    82 #  -d, --data-relocs       process data relocations
    83 #  -r, --function-relocs   process data and function relocations
    84 #  -u, --unused            print unused direct dependencies
    85 #  -v, --verbose           print all information
    86 
    87 # See also this thread:
    88 #  http://sourceware.org/ml/crossgcc/2008-09/msg00057.html
    89 }
    90 
    91 # Parse command line options
    92 root="${CT_XLDD_ROOT}"
    93 show_system=
    94 while true; do
    95     case "${1}" in
    96         --help)
    97             show_help
    98             exit 0
    99             ;;
   100         --version)
   101             show_version
   102             exit 0
   103             ;;
   104         --root)
   105             root="$2"
   106             shift
   107             ;;
   108         --root=*)
   109             root="${1#--root=}"
   110             ;;
   111         --show-system|-s)
   112             show_system=1
   113             ;;
   114         -*)
   115             do_opt_error "unrecognized option \`${1}'"
   116             exit 1
   117             ;;
   118         *)
   119             break
   120             ;;
   121     esac
   122     shift
   123 done
   124 
   125 # Sanity checks
   126 if [ -z "${root}" ]; then
   127     do_opt_error "no root given"
   128     exit 1
   129 fi
   130 if [ ! -d "${root}" ]; then
   131     do_error "\`${root}': no such file or directory"
   132     exit 1
   133 fi
   134 
   135 sysroot="$( "${gcc}" -print-sysroot )"
   136 
   137 do_report_needed_found() {
   138     local needed="${1}"
   139     local path="${2}"
   140     local system="${3}"
   141     local loadaddr
   142     local sys
   143 
   144     if [ -z "${system}" ]; then
   145         loadaddr="${fake_load_addr}"
   146     else
   147         loadaddr="${fake_load_addr_sys}"
   148         if [ -n "${show_system}" ]; then
   149             sys=" [*]"
   150         fi
   151     fi
   152 
   153     # 8 to fake a 32-bit load address
   154     printf "%8s%s => %s (0x%0*x)%s\n"   \
   155            ""                           \
   156            "${needed}"                  \
   157            "${path}"                    \
   158            8                            \
   159            "${loadaddr}"                \
   160            "${sys}"
   161 }
   162 
   163 # Search a needed file, scanning ${lib_dir} in the root directory
   164 do_find_needed() {
   165     local needed="${1}"
   166     local found
   167     local found_sysroot
   168     local d
   169 
   170     for d in "${needed_search_path[@]}"; do
   171         if [ -f "${root}${d}/${needed}" ]; then
   172             found="${d}/${needed}"
   173         fi
   174     done
   175     if [ -z "${found}" ]; then
   176     for d in "${needed_search_path[@]}"; do
   177         if [ -f "${sysroot}${d}/${needed}" ]; then
   178             found_sysroot="${d}/${needed}"
   179         fi
   180     done
   181     fi
   182 
   183     if [ -n "${found}" ]; then
   184         do_report_needed_found "${needed}" "${found}"
   185         do_process_file "${root}${found}"
   186     elif [ -n "${found_sysroot}" ]; then
   187         do_report_needed_found "${needed}" "${found_sysroot}" "sys"
   188         do_process_file "${sysroot}${found_sysroot}"
   189     else
   190         printf "%8c%s not found\n" "" "${needed}"
   191     fi
   192 }
   193 
   194 # Scan a file for all NEEDED tags
   195 do_process_file() {
   196     local file="${1}"
   197 
   198     "${readelf}" -d "${file}"                                           \
   199     |"${grep}" -E '\(NEEDED\)'                                          \
   200     |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;'    \
   201     |while read needed; do
   202         do_find_needed "${needed}"
   203      done
   204 }
   205 
   206 # Build up the full list of search directories
   207 declare -a needed_search_path
   208 ld_library_path="${ld_library_path}:"
   209 while [ -n "${ld_library_path}" ]; do
   210     d="${ld_library_path%%:*}"
   211     [ -n "${d}" ] && needed_search_path+=( "${d}" )
   212     ld_library_path="${ld_library_path#*:}"
   213 done
   214 
   215 do_process_file "${1}"