1#!/bin/sh 2 3libkey() { 4 libkey="lib_symbols_$1" 5 patterns=[.+,/-] 6 replacement=_ 7 while :; do 8 case " ${libkey} " in 9 *${patterns}*) 10 libkey="${libkey%%${patterns}*}${replacement}${libkey#*${patterns}}" 11 ;; 12 *) 13 break 14 ;; 15 esac 16 done 17 return 0 18} 19 20usage() { 21 cat <<-EOF 22 usage: $0 [-Uv] [-L LD_LIBRARY_PATH] file 23 -L: Specify an alternative LD_LIBRARY_PATH for the library resolution. 24 -U: Skip looking for unresolved symbols. 25 -v: Show which library each symbol is resolved to. 26 EOF 27 exit 0 28} 29 30ret=0 31CHECK_UNRESOLVED=1 32VERBOSE_RESOLVED=0 33while getopts "L:Uv" flag; do 34 case "${flag}" in 35 L) LIB_PATH="${OPTARG}" ;; 36 U) CHECK_UNRESOLVED=0 ;; 37 v) VERBOSE_RESOLVED=1 ;; 38 *) usage ;; 39 esac 40done 41shift $((OPTIND-1)) 42 43if ! [ -f "$1" ]; then 44 echo "No such file or directory: $1" >&2 45 exit 1 46fi 47 48mime=$(file -L --mime-type $1) 49isbin=0 50case $mime in 51*application/x-executable|*application/x-pie-executable) isbin=1 ;; 52*application/x-sharedlib);; 53*) echo "Not an elf file" >&2 ; exit 1;; 54esac 55 56# Gather all symbols from the target 57unresolved_symbols=$(nm -u -D --format=posix "$1" | awk '$2 == "U" {print $1}' | tr '\n' ' ') 58[ ${isbin} -eq 1 ] && bss_symbols=$(nm -D --format=posix "$1" | awk '$2 == "B" && $4 != "" {print $1}' | tr '\n' ' ') 59if [ -n "${LIB_PATH}" ]; then 60 for libc in /lib/libc.so.*; do 61 LDD_ENV="LD_PRELOAD=${libc}" 62 done 63 LDD_ENV="${LDD_ENV} LD_LIBRARY_PATH=${LIB_PATH}" 64fi 65 66ldd_libs=$(env ${LDD_ENV} ldd $(realpath $1) | awk '{print $1 ":" $3}') 67 68# Check for useful libs 69list_libs= 70resolved_symbols= 71for lib in $(readelf -d $1 | awk '$2 ~ /\(?NEEDED\)?/ { sub(/\[/,"",$NF); sub(/\]/,"",$NF); print $NF }'); do 72 echo -n "checking if $lib is needed: " 73 if [ -n "${lib##/*}" ]; then 74 for libpair in ${ldd_libs}; do 75 case "${libpair}" in 76 ${lib}:*) libpath="${libpair#*:}" && break ;; 77 esac 78 done 79 else 80 libpath="${lib}" 81 fi 82 list_libs="$list_libs $lib" 83 foundone= 84 lib_symbols="$(nm -D --defined-only --format=posix "${libpath}" | awk '$2 ~ /C|R|D|T|W|B|V/ {print $1}' | tr '\n' ' ')" 85 if [ ${CHECK_UNRESOLVED} -eq 1 ]; then 86 # Save the global symbols for this lib 87 libkey "${lib}" 88 setvar "${libkey}" "${lib_symbols}" 89 fi 90 for fct in ${lib_symbols}; do 91 case " ${unresolved_symbols} ${bss_symbols} " in 92 *\ ${fct}\ *) foundone="${fct}" && break ;; 93 esac 94 done 95 if [ -n "${foundone}" ]; then 96 echo "yes... ${foundone}" 97 else 98 echo "no" 99 ret=1 100 fi 101done 102 103if [ ${CHECK_UNRESOLVED} -eq 1 ]; then 104 # Add in crt1 symbols 105 list_libs="${list_libs} crt1.o" 106 lib_symbols="$(nm --defined-only --format=posix "/usr/lib/crt1.o" | awk '$2 ~ /C|R|D|T|W|B|V/ {print $1}' | tr '\n' ' ')" 107 # Save the global symbols for this lib 108 libkey "crt1.o" 109 setvar "${libkey}" "${lib_symbols}" 110 111 # Now search libs for all symbols and report missing ones. 112 for sym in ${unresolved_symbols}; do 113 found=0 114 for lib in ${list_libs}; do 115 libkey "${lib}" 116 eval "lib_symbols=\"\${${libkey}}\"" 117 # lib_symbols now contains symbols for the lib. 118 case " ${lib_symbols} " in 119 *\ ${sym}\ *) 120 [ ${VERBOSE_RESOLVED} -eq 1 ] && 121 echo "Resolved symbol ${sym} from ${lib}" 122 found=1 123 break 124 ;; 125 esac 126 done 127 if [ $found -eq 0 ]; then 128 echo "Unresolved symbol $sym" 129 ret=1 130 fi 131 done 132fi 133 134exit ${ret} 135