Merge pull request #55538 from worldofpeace/autopatchelf-backport

backport changes to autoPatchelfHook
This commit is contained in:
John Ericson
2019-02-13 09:57:59 -05:00
committed by GitHub
2 changed files with 75 additions and 27 deletions

View File

@@ -7,21 +7,16 @@ gatherLibraries() {
addEnvHooks "$targetOffset" gatherLibraries
isExecutable() {
[ "$(file -b -N --mime-type "$1")" = application/x-executable ]
}
findElfs() {
find "$1" -type f -exec "$SHELL" -c '
while [ -n "$1" ]; do
mimeType="$(file -b -N --mime-type "$1")"
if [ "$mimeType" = application/x-executable \
-o "$mimeType" = application/x-pie-executable \
-o "$mimeType" = application/x-sharedlib ]; then
echo "$1"
fi
shift
done
' -- {} +
# For dynamically linked ELF files it would be enough to check just for the
# INTERP section. However, we won't catch statically linked executables as
# they only have an ELF type of EXEC but no INTERP.
#
# So what we do here is just check whether *either* the ELF type is EXEC
# *or* there is an INTERP section. This also catches position-independent
# executables, as they typically have an INTERP section but their ELF type
# is DYN.
LANG=C readelf -h -l "$1" 2> /dev/null \
| grep -q '^ *Type: *EXEC\>\|^ *INTERP\>'
}
# We cache dependencies so that we don't need to search through all of them on
@@ -152,24 +147,73 @@ autoPatchelfFile() {
fi
}
# Can be used to manually add additional directories with shared object files
# to be included for the next autoPatchelf invocation.
addAutoPatchelfSearchPath() {
local -a findOpts=()
# XXX: Somewhat similar to the one in the autoPatchelf function, maybe make
# it DRY someday...
while [ $# -gt 0 ]; do
case "$1" in
--) shift; break;;
--no-recurse) shift; findOpts+=("-maxdepth" 1);;
--*)
echo "addAutoPatchelfSearchPath: ERROR: Invalid command line" \
"argument: $1" >&2
return 1;;
*) break;;
esac
done
cachedDependencies+=(
$(find "$@" "${findOpts[@]}" \! -type d \
\( -name '*.so' -o -name '*.so.*' \))
)
}
autoPatchelf() {
local norecurse=
while [ $# -gt 0 ]; do
case "$1" in
--) shift; break;;
--no-recurse) shift; norecurse=1;;
--*)
echo "autoPatchelf: ERROR: Invalid command line" \
"argument: $1" >&2
return 1;;
*) break;;
esac
done
if [ $# -eq 0 ]; then
echo "autoPatchelf: No paths to patch specified." >&2
return 1
fi
echo "automatically fixing dependencies for ELF files" >&2
# Add all shared objects of the current output path to the start of
# cachedDependencies so that it's choosen first in findDependency.
cachedDependencies+=(
$(find "$prefix" \! -type d \( -name '*.so' -o -name '*.so.*' \))
)
local elffile
addAutoPatchelfSearchPath ${norecurse:+--no-recurse} -- "$@"
# Here we actually have a subshell, which also means that
# $cachedDependencies is final at this point, so whenever we want to run
# findDependency outside of this, the dependency cache needs to be rebuilt
# from scratch, so keep this in mind if you want to run findDependency
# outside of this function.
findElfs "$prefix" | while read -r elffile; do
autoPatchelfFile "$elffile"
done
while IFS= read -r -d $'\0' file; do
isELF "$file" || continue
segmentHeaders="$(LANG=C readelf -l "$file")"
# Skip if the ELF file doesn't have segment headers (eg. object files).
echo "$segmentHeaders" | grep -q '^Program Headers:' || continue
if isExecutable "$file"; then
# Skip if the executable is statically linked.
echo "$segmentHeaders" | grep -q "^ *INTERP\\>" || continue
fi
autoPatchelfFile "$file"
done < <(find "$@" ${norecurse:+-maxdepth 1} -type f -print0)
}
# XXX: This should ultimately use fixupOutputHooks but we currently don't have
@@ -180,6 +224,11 @@ autoPatchelf() {
# So what we do here is basically run in postFixup and emulate the same
# behaviour as fixupOutputHooks because the setup hook for patchelf is run in
# fixupOutput and the postFixup hook runs later.
postFixupHooks+=(
'for output in $outputs; do prefix="${!output}" autoPatchelf; done'
)
postFixupHooks+=('
if [ -z "$dontAutoPatchelf" ]; then
autoPatchelf -- $(for output in $outputs; do
[ -e "${!output}" ] || continue
echo "${!output}"
done)
fi
')

View File

@@ -81,8 +81,7 @@ with pkgs;
{ deps = [ autoconf264 automake111x gettext libtool ]; }
../build-support/setup-hooks/autoreconf.sh;
autoPatchelfHook = makeSetupHook
{ name = "auto-patchelf-hook"; deps = [ file ]; }
autoPatchelfHook = makeSetupHook { name = "auto-patchelf-hook"; }
../build-support/setup-hooks/auto-patchelf.sh;
ensureNewerSourcesHook = { year }: makeSetupHook {}