mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-02 13:00:23 +00:00
Merge pull request #55538 from worldofpeace/autopatchelf-backport
backport changes to autoPatchelfHook
This commit is contained in:
@@ -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
|
||||
')
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
Reference in New Issue
Block a user