Script : find shared library dependencies
Monday, 19 July 2021
|
While developping the reverse of Adobe's library libRMSDK.so, I needed a script to find all dependencies of this library and dependencies of dependencies. All of them must be copied into one folder in order to be packaged. So I wrote this script that parses recursively objdump's ouput. Here is the code :
#!/bin/bash
# Copyright Grégory Soutadé
# This is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iwla. If not, see <http://www.gnu.org/licenses/>.
#
#
# Find all dependant shared libraries of a target (using objdump) and copy them into a directory
#
# Options
TARGET=""
OUTPUT=""
ROOT_LIB_DIRECTORY=""
OBJDUMP=objdump
VERBOSE=0
EXIT_ON_ERROR=0
QUIET_NOT_FOUND=0
CLEAN_BEFORE_START=0
COPY_TARGET=0
function debug()
{
if [ $VERBOSE -eq 1 ] ; then
echo -e "$1"
fi
}
function copy()
{
target=$1
symlink_name=$2
if [ ! -e ${target} ] ; then
debug "${target} not found"
return
fi
debug "cp --no-dereference ${target} ${OUTPUT}"
cp --no-dereference ${target} ${OUTPUT}
if [ ! $? -eq 0 ] ; then
[ ${EXIT_ON_ERROR} -eq 1 ] && exit 1
return
fi
if [ ! -z "${symlink_name}" ] ; then
echo ln -s `basename ${target}` ${OUTPUT}/${symlink_name}
ln -s `basename ${target}` ${OUTPUT}/${symlink_name}
fi
# Symlink ? Copy target file
if [ -L ${target} ] ; then
copy `readlink -e ${target}`
fi
}
nb_tabs=0
function find_lib()
{
target="$1"
if [ ! -e ${target} ] ; then
debug "${target} not found"
return
fi
nb_tabs=$((${nb_tabs}+1))
local tabs=""
for i in `seq 1 ${nb_tabs}`; do
tabs="${tabs} "
done
dependencies=`${OBJDUMP} -p ${target}|grep NEEDED|sed "s/ \+/ /g"|cut -d' ' -f3`
for dependency in ${dependencies} ; do
symlink_name=""
echo -e "${tabs}${dependency}"
debug "find ${ROOT_LIB_DIRECTORY} -name ${dependency}"
file=`find ${ROOT_LIB_DIRECTORY} -name ${dependency}|head -n 1`
if [ -z "$file" ] ; then
# Try lib.so*
file=`find ${ROOT_LIB_DIRECTORY} -name ${dependency}*|head -n 1`
if [ -z "$file" ] ; then
[ ${QUIET_NOT_FOUND} -eq 0 ] && echo "ERROR : ${dependency} not found in ${ROOT_LIB_DIRECTORY}"
[ ${EXIT_ON_ERROR} -eq 1 ] && exit 1
continue
else
symlink_name=${dependency}
fi
fi
# Already copied
[ -e "${OUTPUT}/${dependency}" ] && continue
copy $file ${symlink_name}
find_lib $file
done
nb_tabs=$((${nb_tabs}-1))
}
function usage()
{
echo "Usage : ./find_libs [-O OBJDUMP] [-v] [-e] [-q] [-c] [-C] -t TARGET -o OUTPUT_DIR -l ROOT_LIBDIR"
echo -e "\t-O OBJDUMP objdump command"
echo -e "\t-v verbose"
echo -e "\t-e exit on error"
echo -e "\t-q quiet when dependency not found"
echo -e "\t-c clean target before start"
echo -e "\t-C Copy target in output directory"
echo -e "\t-t TARGET first executable or library to analyze"
echo -e "\t-o OUTPUT_DIR output directory where to place find libs"
echo -e "\t-l ROOT_LIBDIR root directory where to search dependancy libs"
}
while getopts "ht:o:l:O:veqcC" arg; do
case $arg in
t)
TARGET=$OPTARG
;;
o)
OUTPUT=$OPTARG
;;
l)
ROOT_LIB_DIRECTORY=$OPTARG
;;
O)
OBJDUMP=$OPTARG
;;
v)
VERBOSE=1
;;
e)
EXIT_ON_ERROR=1
;;
q)
QUIET_NOT_FOUND=1
;;
c)
CLEAN_BEFORE_START=1
;;
C)
COPY_TARGET=1
;;
h)
usage
;;
*)
usage
;;
esac
done
if [ -z "${TARGET}" -o -z "${OUTPUT}" -o -z "${ROOT_LIB_DIRECTORY}" ] ; then
usage
exit 0
fi
[ ${CLEAN_BEFORE_START} -eq 1 ] && rm -rf ${OUTPUT}
mkdir -p ${OUTPUT} || exit 1
echo ${TARGET}
[ ${COPY_TARGET} -eq 1 ] && copy ${TARGET}
find_lib ${TARGET}
A file version is available here