-
Notifications
You must be signed in to change notification settings - Fork 0
/
ldd.sh
executable file
·130 lines (116 loc) · 4.13 KB
/
ldd.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/bin/bash
# This bash script is inspired by 'ldd' of crosstool-ng-1.22.0
# It uses find, readlink, basename and readelf
# mkrootfs.sh is a bash script for compile and create a rootfs for embedded systems.
# Copyright (C) 2016-17 MParolari <mparolari.dev@gmail.com>
#
# This program 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 program 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 this program. If not, see <http://www.gnu.org/licenses/>.
# where the executables files are in the rootfs
declare -ar EXE_PATH=( "/bin" "/sbin" "/usr/bin" "/usr/sbin" )
# where the libraries are in the rootfs
declare -ar LD_LIBRARY_PATH=( "/lib" "/usr/lib" )
# NB: remember the root slash / at the beginning
# This variables (strings) should be set by the caller of this script
# CROSS_CHAIN # GNU crosstool chain
# DIR_ROOT # path of the rootfs
# DIR_ROOT_LIB # path of the 'sysroot'
# Standard output language (or regex won't match the output of readelf)
declare -x LC_ALL=C
# Save original IFS
declare -r OLD_IFS=$IFS
if [ ! -d "${DIR_ROOT}" ]; then
echo "Root directory '${DIR_ROOT}' is not a directory" >&2
exit 1
fi
if [ ! -d "${DIR_ROOT_LIB}" ]; then
echo "Root lib directory '${DIR_ROOT_LIB}' is not a directory" >&2
exit 1
fi
# queue of files that can have dependencies
declare -a FILES
# integer variables for C-like for loop
declare -i i
declare -i j
# for all the search paths
for DIR in "${EXE_PATH[@]}"; do
# if the directory exists
if [ -d "${DIR_ROOT}${DIR}" ]; then
# list all the executables inside it
IFS=$'\n'
for EXE in $( find "${DIR_ROOT}${DIR}" -mindepth 1 -maxdepth 1 ); do
# follow symlinks
EXE="$(readlink -f $EXE)"
# search for it in the list, if present: continue
for (( i = 0; i < ${#FILES[@]}; i++ )); do
[[ "$EXE" == "${FILES[$i]}" ]] && continue 2
done
# if not present, append it
FILES+=( "$EXE" )
done
IFS=$OLD_IFS
fi
done
# until the queue is not empty
for (( i = 0; i < ${#FILES[@]}; i++ )); do
# parse readelf output
IFS=$'\n'
for LINE in $( "${CROSS_CHAIN}readelf" -d "${FILES[$i]}" ); do
# regex captures the NEEDED library name
if [[ "${LINE}" =~ \(NEEDED\).*Shared\ library:[[:space:]]+\[([^]]+)\] ]]; then
LIBS+=( "${BASH_REMATCH[1]}" ) # append it
fi
done
IFS=$OLD_IFS
# for each NEEDED library
for LIB in "${LIBS[@]}"; do
# if the library is already in the list, continue
for (( j = 0; j < ${#NEEDED_LIST[@]}; j++ )); do
[[ "${LIB}" == "${NEEDED_LIST[$j]}" ]] && continue 2
done
# append the library to the list
NEEDED_LIST+=( "${LIB}" )
declare FOUND=""
# for all the search path
for DIR in "${LD_LIBRARY_PATH[@]}"; do
# if this library exists
if [ -f "${DIR_ROOT_LIB}${DIR}/${LIB}" ]; then
FOUND="${DIR}/${LIB}"
break
fi
done
# print if the library is found
if [ -n "${FOUND}" ]; then
# for every reference (symlinks and itself) to that library
IFS=$'\n'
for REF in $(find -L "${DIR_ROOT_LIB}" -samefile "${DIR_ROOT_LIB}${FOUND}"); do
# path of the reference
PATH_REF="${REF#${DIR_ROOT_LIB}}"
# if the reference is already been found and printed, continue
for (( j = 0; j < ${#REF_LIST[@]}; j++ )); do
[[ "${PATH_REF}" == "${REF_LIST[$j]}" ]] && continue 2
done
# print the reference
echo "$(basename "$REF"):${PATH_REF}"
# append to the list (it won't be printed again)
REF_LIST+=( "${PATH_REF}" )
done
IFS=$OLD_IFS
# append the library, it will be analyzed at next loop
FILES+=( "${DIR_ROOT_LIB}${FOUND}" )
else
echo "${LIB}:not_found"
fi
done
done
exit 0