scripts/xldd.in
changeset 2193 4908fb8bae20
parent 2192 cbd4539a86ca
child 2546 ecd9d85a4f2e
     1.1 --- a/scripts/xldd.in	Tue Nov 23 21:36:01 2010 +0100
     1.2 +++ b/scripts/xldd.in	Wed Nov 24 21:04:55 2010 +0100
     1.3 @@ -12,6 +12,7 @@
     1.4  gcc="${prefix}-gcc"
     1.5  readelf="${prefix}-readelf"
     1.6  fake_load_addr_root="$((0xdeadbeef))"
     1.7 +fake_load_addr_rpath="$((0xdeadc0de))"
     1.8  fake_load_addr_sysroot="$((0x8badf00d))"
     1.9  ld_library_path="/lib:/usr/lib"
    1.10  
    1.11 @@ -53,6 +54,7 @@
    1.12        --version           print version information and exit
    1.13        --root dir          treat dir as being the root of the target
    1.14    -s, --show-system       mark libs from the sysroot with a trailing '[*]'
    1.15 +                          and libs found via RPATH with a trailing '[+]'
    1.16  
    1.17  _EOF_
    1.18      cat <<_EOF_ |fmt
    1.19 @@ -70,6 +72,12 @@
    1.20  ${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf
    1.21  (it understands the include directives therein for libces that have that).
    1.22  
    1.23 +${my_name} also interprets (tries to!) the RPATH/RUNPATH records found in
    1.24 +the dynamic ELF section. Such paths are searched for only relative to
    1.25 +the specified root, not from the sysroot (see below). Also, those paths
    1.26 +are searched for not only for the file they appear in, but also for its
    1.27 +dependencies.
    1.28 +
    1.29  ${my_name} will search the directory specified with --root for libraries
    1.30  to resolve the NEEDED tags. If --root is not set, then ${my_name} will
    1.31  use the value in the environment variable \${CT_XLDD_ROOT}. If neither
    1.32 @@ -90,7 +98,8 @@
    1.33  
    1.34  The expected load address 'loadaddr' is a faked address to match the output
    1.35  of the real ldd, but has no actual meaning (set to some constants for now,
    1.36 -0x8badf00d for libraries from the sysroot, 0xdeadbeef for others).
    1.37 +0x8badf00d for libraries from the sysroot, 0xdeadc0de for those found via
    1.38 +the RPATH/RUNPATH records, and 0xdeadbeef for others).
    1.39  _EOF_
    1.40  
    1.41  # Unimplemeted yet:
    1.42 @@ -168,6 +177,12 @@
    1.43          root)
    1.44              loadaddr="${fake_load_addr_root}"
    1.45              ;;
    1.46 +        rpath)
    1.47 +            loadaddr="${fake_load_addr_rpath}"
    1.48 +            if [ -n "${show_system}" ]; then
    1.49 +                sys=" [+]"
    1.50 +            fi
    1.51 +            ;;
    1.52          sysroot)
    1.53              loadaddr="${fake_load_addr_sysroot}"
    1.54              if [ -n "${show_system}" ]; then
    1.55 @@ -189,6 +204,7 @@
    1.56  do_find_needed() {
    1.57      local needed="${1}"
    1.58      local -a list
    1.59 +    local -a dirs
    1.60      local found
    1.61      local where
    1.62      local base
    1.63 @@ -196,7 +212,9 @@
    1.64  
    1.65      do_trace "Searching for '${needed}'\n"
    1.66  
    1.67 +    # rpath shall come first!
    1.68      list=(                      \
    1.69 +        "rpath:${root}"         \
    1.70          "root:${root}"          \
    1.71          "sysroot:${sysroot}"    \
    1.72      )
    1.73 @@ -204,7 +222,12 @@
    1.74      for i in "${list[@]}"; do
    1.75          where="${i%%:*}"
    1.76          base="${i#*:}"
    1.77 -        for d in "${needed_search_path[@]}"; do
    1.78 +        if [ "${where}" = "rpath" ]; then
    1.79 +            dirs=( "${search_rpath[@]}" )
    1.80 +        else
    1.81 +            dirs=( "${needed_search_path[@]}" )
    1.82 +        fi
    1.83 +        for d in "${dirs[@]}"; do
    1.84              do_trace "-> looking in '${d}' (${where})\n"
    1.85              if [ -f "${base}${d}/${needed}" ]; then
    1.86                  found="${d}/${needed}"
    1.87 @@ -225,11 +248,25 @@
    1.88  # Scan a file for all NEEDED tags
    1.89  do_process_file() {
    1.90      local file="${1}"
    1.91 +    local -a save_search_rpath
    1.92      local n m
    1.93      local found
    1.94  
    1.95      do_trace "Parsing file '${file}'\n"
    1.96  
    1.97 +    save_search_rpath=( "${search_rpath[@]}" )
    1.98 +    for n in $( "${readelf}" -d "${file}"                                           \
    1.99 +                |"${grep}" -E '\((RPATH|RUNPATH)\)'                                 \
   1.100 +                |"${sed}" -r -e 's/^.*Library r(|un)path:[[:space:]]+\[(.*)\]$/\2/;'\
   1.101 +              ); do
   1.102 +        do_trace "-> adding rpath '${n}'\n"
   1.103 +        search_rpath+=( "${n}" )
   1.104 +    done
   1.105 +    do_trace ": search path:\n"
   1.106 +    for n in "${search_rpath[@]}" "${needed_search_path[@]}"; do
   1.107 +        do_trace ": - '${n}'\n"
   1.108 +    done
   1.109 +
   1.110      for n in $( "${readelf}" -d "${file}"                                           \
   1.111                  |"${grep}" -E '\(NEEDED\)'                                          \
   1.112                  |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;'    \
   1.113 @@ -245,7 +282,9 @@
   1.114          do_trace "-> handling new dependency '${n}'\n"
   1.115          needed_list+=( "${n}" )
   1.116          do_find_needed "${n}"
   1.117 -     done
   1.118 +    done
   1.119 +
   1.120 +    search_rpath=( "${save_search_rpath[@]}" )
   1.121  }
   1.122  
   1.123  # Recursively scan a /etc/ld.so.conf file
   1.124 @@ -297,4 +336,5 @@
   1.125  
   1.126  do_trace "Scanning file '${1}'\n"
   1.127  declare -a needed_list
   1.128 +declare -a search_rpath
   1.129  do_process_file "${1}"