3

I'm analysing a large C++ project on linux platform(redhat), specifically the shared libraries used in it. How can I find which symbols(functions/variables) are used in this project from a particular shared library?

To begin I ran the following command on my binary:

readelf -d binaryName | grep -i "Shared library"

and I got a list of shared libraries which are used in my project(ldd shows a longer list as these shared libraries have their own dependencies as well) e.g.

 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libuv.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libssl.so.1.1]
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so.1.1]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Now is there a way to find out which symbols from, say, libuv.so.1 are used in the project's codebase. Can anyone suggest some roadmap?

2 Answers 2

3
nm -uD /path/to/your/binary

will list all the undefined dynamic symbols in your binary. You then need to match that with the output of

nm -gD /path/to/a/library

for each library listed by your readelf command to determine which library provides each symbol.

Note that this doesn’t necessarily give a complete picture; in particular, libraries and symbols accessed through libdl won’t be taken into account. If you’re willing to run the binary, and it uses the GNU C library’s dynamic loader (ld.so, or rather ld-linux.so on Linux), you can list all the symbol bindings in detail by running the binary with LD_DEBUG=bindings set in its environment. See man ld.so for details.

3
  • 'nm -gD /path/to/library' outputs different types of symbols e.g. T, W, U, i, A etc. Would you agree that I need to skip the U category? If yes, are there some other categories which I need to skip? Is there a flag which will just give me the required(for my case) category of symbols? Commented Jan 25, 2022 at 6:12
  • 1
    If you’re only interested in functions, you can ignore everything apart from T. I’m not aware of a flag to do that. Commented Jan 25, 2022 at 6:31
  • It may be useful to add the -U option when inspecting the library to limit to symbols which are defined in that library.
    – DBear
    Commented May 4 at 1:55
2

Using the information provided in the accepted answer and here, I've created the following script for finding all the symbols which are currently being used in the binary(taken from the shared library). The script takes 1 argument i.e. the name of the binary(path required if binary is in a different directory than the script).

The script will display the shared libraries needed by the binary file given in input. All the symbols will be dumped into an output file(result.txt)

#!/bin/bash

if [ "$#" -ne 1 ]
then
    echo "1 argument needed in the script"
    echo "e.g. $0 [binary name(complete path)]"
    exit
fi

if [ -f $1 ]
then
    echo "Going to find the unresolved symbols found in \"$1\""
else
    echo "Binary file \"$1\" not found. Check name/path."
fi

binaryFile=$1

lddOutput=(`ldd $binaryFile | awk '{print $3}' | grep -v "0x" | awk 'NF >0'`)

#echo "$lddOutput"

sharedDependencies=()

echo "Given below are the shared libraries used in $1"
for lib in "${lddOutput[@]}"
do
    sharedDependencies+=($lib)
    ls -lrta $lib
done

rm -f allSymbols.temp
rm -f result.txt

# Iterate the loop to read and print each array element
#echo -e "\nGiven below are the dependencies found for $binaryFile\n"
#echo "SharedDependencies: ${sharedDependencies}"
for lib in "${sharedDependencies[@]}"
do
#echo "Will search below lib in sharedDependencies"
#echo $lib
#Create list of all text symbols from all the libraries
#for symbol in `nm -gD $lib | awk '{$1=""}1' | grep " T \| W \| V \| w \| v \| t " | awk '{print $2}'`;
#for symbol in `nm -gD $lib | grep -i " T \| W \| V "`;
nm -gD $lib | grep -i " T \| W \| V \| I " | while read symbol;
do
string=
sym=
#echo -e "\nsymbol->$symbol" >> debug.txt
n=`echo $symbol | awk "{print NF}"`
#echo -e "n->$n\n" >> debug.txt
if [ $n -eq 2 ]
then
sym=`echo $symbol | awk '{print $2}'`
else
sym=`echo $symbol | awk '{print $3}'`
fi

string="$lib contains $sym"
echo $string >> allSymbols.temp
#echo $string >> debug.txt
done
done

undefinedDynamicSymbols=`nm -uD $binaryFile | awk '{print $2}'`
#echo -e "\n\nUndefinedDynamicSymbols\n$undefinedDynamicSymbols\n"

for undefinedSymbol in $undefinedDynamicSymbols;
do
echo $undefinedSymbol >> result.txt
grep  -w $undefinedSymbol allSymbols.temp >> result.txt
echo -e "\n" >> result.txt
done

echo "symbols dumped in result.txt"

rm -f allSymbols.temp

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .