![Thomas Petazzoni](/assets/img/avatar_default.png)
As suggested by Arnout Vandecappelle, let's document the elf_needs_rpath() and check_elf_has_rpath() functions, before we make them a bit more complicated with per-package directory support. Suggested-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Reviewed-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
90 lines
2.9 KiB
Bash
Executable file
90 lines
2.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
# This script scans $(HOST_DIR)/{bin,sbin} for all ELF files, and checks
|
|
# they have an RPATH to $(HOST_DIR)/lib if they need libraries from
|
|
# there.
|
|
|
|
# Override the user's locale so we are sure we can parse the output of
|
|
# readelf(1) and file(1)
|
|
export LC_ALL=C
|
|
|
|
main() {
|
|
local pkg="${1}"
|
|
local hostdir="${2}"
|
|
local file ret
|
|
|
|
# Remove duplicate and trailing '/' for proper match
|
|
hostdir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${hostdir}" )"
|
|
|
|
ret=0
|
|
while read file; do
|
|
is_elf "${file}" || continue
|
|
elf_needs_rpath "${file}" "${hostdir}" || continue
|
|
check_elf_has_rpath "${file}" "${hostdir}" && continue
|
|
if [ ${ret} -eq 0 ]; then
|
|
ret=1
|
|
printf "***\n"
|
|
printf "*** ERROR: package %s installs executables without proper RPATH:\n" "${pkg}"
|
|
fi
|
|
printf "*** %s\n" "${file}"
|
|
done < <( find "${hostdir}"/{bin,sbin} -type f 2>/dev/null )
|
|
|
|
return ${ret}
|
|
}
|
|
|
|
is_elf() {
|
|
local f="${1}"
|
|
|
|
readelf -l "${f}" 2>/dev/null \
|
|
|grep -E 'Requesting program interpreter:' >/dev/null 2>&1
|
|
}
|
|
|
|
# This function tells whether a given ELF executable (first argument)
|
|
# needs a RPATH pointing to the host library directory or not. It
|
|
# needs such an RPATH if at least of the libraries used by the ELF
|
|
# executable is available in the host library directory. This function
|
|
# returns 0 when a RPATH is needed, 1 otherwise.
|
|
elf_needs_rpath() {
|
|
local file="${1}"
|
|
local hostdir="${2}"
|
|
local lib
|
|
|
|
while read lib; do
|
|
[ -e "${hostdir}/lib/${lib}" ] && return 0
|
|
done < <( readelf -d "${file}" \
|
|
|sed -r -e '/^.* \(NEEDED\) .*Shared library: \[(.+)\]$/!d;' \
|
|
-e 's//\1/;' \
|
|
)
|
|
|
|
return 1
|
|
}
|
|
|
|
# This function checks whether at least one of the RPATH of the given
|
|
# ELF executable (first argument) properly points to the host library
|
|
# directory (second argument), either through an absolute RPATH or a
|
|
# relative RPATH. Having such a RPATH will make sure the ELF
|
|
# executable will find at runtime the shared libraries it depends
|
|
# on. This function returns 0 when a proper RPATH was found, or 1
|
|
# otherwise.
|
|
check_elf_has_rpath() {
|
|
local file="${1}"
|
|
local hostdir="${2}"
|
|
local rpath dir
|
|
|
|
while read rpath; do
|
|
for dir in ${rpath//:/ }; do
|
|
# Remove duplicate and trailing '/' for proper match
|
|
dir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${dir}" )"
|
|
[ "${dir}" = "${hostdir}/lib" ] && return 0
|
|
[ "${dir}" = "\$ORIGIN/../lib" ] && return 0
|
|
done
|
|
done < <( readelf -d "${file}" \
|
|
|sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d' \
|
|
-e 's//\3/;' \
|
|
)
|
|
|
|
return 1
|
|
}
|
|
|
|
main "${@}"
|