mirror of
https://git.busybox.net/buildroot.git
synced 2024-11-27 07:23:30 +08:00
2100a76d9e
Commit a87abcf6da
(Makefile: run PPD and RPATH fixup in host-fialize)
(sic) moved the fixups peviously done in prepare-sdk, to host-finalize.
This exposed a bug in fix-rpath, when RPATH contains multiple entries,
like: /PPD/host-foo/host/lib:/PPD/host-foo/host/lib/foo
In that situation, we want to get rid of /PPD/host-foo and replace it
with the finale HOST_DIR, so we mangle the RPATH with a sed expression.
However, that sed expression only ever replaces the first match, as it
is missing the 'g' option. Thus, the second (and following) parts of
RPATH are still referring to the PPD, and thus patchelf does not find it
relative to the final HOST_DIR, amd rops it. This eventually lead to a
final RPATH set as $ORIGIN/../lib instead of the expected
$ORIGIN/../lib:$ORIGIN/../lib/foo
This is the case for host-systemd, which installs some of its libraries
in $PREFIX/lib/systemd/ and adds an RPATH set appropriately to
/PPD/host-systemd/host/lib:/PPD/host-systemd/host/lib/systemd and that
gets incorrectly mangled.
Fixes: https://gitlab.com/buildroot.org/buildroot/-/issues/39
Also fix a typo in the comment just above.
Reported-by: José Luis Salvador Rufo @jlsalvador
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
Tested-by: José Luis Salvador Rufo <salvador.joseluis@gmail.com>
Reviewed-by: José Luis Salvador Rufo <salvador.joseluis@gmail.com>
Tested-by: Adam Duskett <adam.duskett@amarulasolutions.com>
Reviewed-by: Adam Duskett <adam.duskett@amarulasolutions.com>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
182 lines
5.8 KiB
Bash
Executable File
182 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Copyright (C) 2016 Samuel Martin <s.martin49@gmail.com>
|
|
# Copyright (C) 2017 Wolfgang Grandegger <wg@grandegger.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 2 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, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
usage() {
|
|
cat <<EOF >&2
|
|
Usage: ${0} TREE_KIND
|
|
|
|
Description:
|
|
|
|
This script scans a tree and sanitize ELF files' RPATH found in there.
|
|
|
|
Sanitization behaves the same whatever the kind of the processed tree,
|
|
but the resulting RPATH differs. The rpath sanitization is done using
|
|
"patchelf --make-rpath-relative".
|
|
|
|
Arguments:
|
|
|
|
TREE_KIND Kind of tree to be processed.
|
|
Allowed values: host, target, staging
|
|
|
|
Environment:
|
|
|
|
PATCHELF patchelf program to use
|
|
(default: HOST_DIR/bin/patchelf)
|
|
|
|
HOST_DIR host directory
|
|
STAGING_DIR staging directory
|
|
TARGET_DIR target directory
|
|
|
|
TOOLCHAIN_EXTERNAL_DOWNLOAD_INSTALL_DIR
|
|
(default HOST_DIR/opt/ext-toolchain)
|
|
|
|
PARALLEL_JOBS number of parallel jobs to run
|
|
|
|
Returns: 0 if success or 1 in case of error
|
|
|
|
EOF
|
|
}
|
|
|
|
: "${PATCHELF:=${HOST_DIR}/bin/patchelf}"
|
|
|
|
# ELF files should not be in these sub-directories
|
|
HOST_EXCLUDEPATHS="/share/terminfo"
|
|
STAGING_EXCLUDEPATHS="/usr/include /usr/share/terminfo"
|
|
TARGET_EXCLUDEPATHS="/lib/firmware"
|
|
|
|
patch_file() {
|
|
local PATCHELF rootdir file
|
|
local -a sanitize_extra_args
|
|
|
|
PATCHELF="${1}"
|
|
rootdir="${2}"
|
|
file="${3}"
|
|
shift 3
|
|
sanitize_extra_args=("${@}")
|
|
|
|
# check if it's an ELF file
|
|
rpath="$("${PATCHELF}" --print-rpath "${file}" 2>&1)"
|
|
if test $? -ne 0 ; then
|
|
return 0
|
|
fi
|
|
|
|
# make files writable if necessary
|
|
changed="$(chmod -c u+w "${file}")"
|
|
|
|
# With per-package directory support, most RPATH of host
|
|
# binaries will point to per-package directories. This won't
|
|
# work with the --make-rpath-relative ${rootdir} invocation as
|
|
# the per-package host directory is not within ${rootdir}. So,
|
|
# we rewrite all RPATHs pointing to per-package directories so
|
|
# that they point to the global host directory.
|
|
# shellcheck disable=SC2001 # ${var//search/replace} hard when search or replace have / in them
|
|
changed_rpath="$(echo "${rpath}" | sed "s@${PER_PACKAGE_DIR}/[^/]\+/host@${HOST_DIR}@g")"
|
|
if test "${rpath}" != "${changed_rpath}" ; then
|
|
"${PATCHELF}" --set-rpath "${changed_rpath}" "${file}"
|
|
fi
|
|
|
|
# call patchelf to sanitize the rpath
|
|
"${PATCHELF}" --make-rpath-relative "${rootdir}" "${sanitize_extra_args[@]}" "${file}"
|
|
# restore the original permission
|
|
test "${changed}" != "" && chmod u-w "${file}"
|
|
}
|
|
|
|
main() {
|
|
local rootdir tree
|
|
local -a find_args sanitize_extra_args
|
|
|
|
tree="${1}"
|
|
|
|
if ! "${PATCHELF}" --version > /dev/null 2>&1; then
|
|
echo "Error: can't execute patchelf utility '${PATCHELF}'"
|
|
exit 1
|
|
fi
|
|
|
|
case "${tree}" in
|
|
host)
|
|
rootdir="${HOST_DIR}"
|
|
|
|
# do not process the sysroot (only contains target binaries)
|
|
find_args+=( "-path" "${STAGING_DIR}" "-prune" "-o" )
|
|
|
|
# do not process the external toolchain installation directory to
|
|
# avoid breaking it.
|
|
test "${TOOLCHAIN_EXTERNAL_DOWNLOAD_INSTALL_DIR}" != "" && \
|
|
find_args+=( "-path" "${TOOLCHAIN_EXTERNAL_DOWNLOAD_INSTALL_DIR}" "-prune" "-o" )
|
|
|
|
for excludepath in ${HOST_EXCLUDEPATHS}; do
|
|
find_args+=( "-path" "${HOST_DIR}""${excludepath}" "-prune" "-o" )
|
|
done
|
|
|
|
# do not process the patchelf binary but a copy to work-around "file in use"
|
|
find_args+=( "-path" "${PATCHELF}" "-prune" "-o" )
|
|
cp "${PATCHELF}" "${PATCHELF}.__to_be_patched"
|
|
|
|
# we always want $ORIGIN-based rpaths to make it relocatable.
|
|
sanitize_extra_args+=( "--relative-to-file" )
|
|
;;
|
|
|
|
staging)
|
|
rootdir="${STAGING_DIR}"
|
|
|
|
# ELF files should not be in these sub-directories
|
|
for excludepath in ${STAGING_EXCLUDEPATHS}; do
|
|
find_args+=( "-path" "${STAGING_DIR}""${excludepath}" "-prune" "-o" )
|
|
done
|
|
|
|
# should be like for the target tree below
|
|
sanitize_extra_args+=( "--no-standard-lib-dirs" )
|
|
;;
|
|
|
|
target)
|
|
rootdir="${TARGET_DIR}"
|
|
|
|
for excludepath in ${TARGET_EXCLUDEPATHS}; do
|
|
find_args+=( "-path" "${TARGET_DIR}""${excludepath}" "-prune" "-o" )
|
|
done
|
|
|
|
# we don't want $ORIGIN-based rpaths but absolute paths without rootdir.
|
|
# we also want to remove rpaths pointing to /lib or /usr/lib.
|
|
sanitize_extra_args+=( "--no-standard-lib-dirs" )
|
|
;;
|
|
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
find_args+=( "-type" "f" "-print0" )
|
|
|
|
export -f patch_file
|
|
# Limit the number of cores used
|
|
# shellcheck disable=SC2016 # ${@} has to be expanded in the sub-shell.
|
|
find "${rootdir}" "${find_args[@]}" \
|
|
| xargs -0 -r -P "${PARALLEL_JOBS:-1}" -I {} \
|
|
bash -c 'patch_file "${@}"' _ "${PATCHELF}" "${rootdir}" {} "${sanitize_extra_args[@]}"
|
|
|
|
# Restore patched patchelf utility
|
|
test "${tree}" = "host" && mv "${PATCHELF}.__to_be_patched" "${PATCHELF}"
|
|
|
|
# ignore errors
|
|
return 0
|
|
}
|
|
|
|
main "${@}"
|