[Buildroot] [PATCH v7 2/9] support/scripts: add fix-rpath script to sanitize the rpath
Wolfgang Grandegger
wg at grandegger.com
Thu Jul 20 07:31:20 UTC 2017
Am 20.07.2017 um 01:02 schrieb Arnout Vandecappelle:
>
>
> On 05-07-17 18:53, Wolfgang Grandegger wrote:
>> From: Samuel Martin <s.martin49 at gmail.com>
>>
>> This commit introduces the script "fix-rpath" able to scan a tree,
>> detect ELF files, check their RPATH and fix it in a proper way.
>> The RPATH fixup is done by the patchelf utility using the option
>> "--make-rpath-relative <root-directory>".
>>
>> Signed-off-by: Samuel Martin <s.martin49 at gmail.com>
>> Signed-off-by: Wolfgang Grandegger <wg at grandegger.com>
>
> Some small comments below, but again, can be fixed in follow-up patches, so
>
> Acked-by: Arnout Vandecappelle (Essensium/Mind) <arnout at mind.be>
>
> [snip]
>> +Description:
>> +
>> + This script scans a tree and sanitize ELF files' RPATH found in there.
> ^s
>> +
>> + 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-relazive".
> ^t
>
>> +
>> +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)
>
> And also HOST_DIR, TARGET_DIR, STAGING_DIR, and
> TOOLCHAIN_EXTERNAL_DOWNLOAD_INSTALL_DIR.
PATCHELF points to the patchelf utility! Or what do you mean here?
>
> [snip]
>> + 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" )
>
> Since this variable isn't exported, it doesn't actually end up being used. But
> I think the solution is to pass it explicitly in patch 5.
>
>> +
>> + for excludepath in ${HOST_EXCLUDEPATHS}; do
>> + find_args+=( "-path" "${HOST_DIR}""${excludepath}" "-prune" "-o" );
>> + done
>
> Perhaps this could be refactored into defining here:
> excludepaths="${HOST_EXCLUDEPATHS}"
> and moving the loop to the generic part. It would anyway be nicer to have
> TARGET_EXCLUDEPATHS, for symmetry.
Will improve that later.
>
>> +
>> + # 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"
>> +
>> + 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
>> +
>> + sanitize_extra_args+=( "--no-standard-lib-dirs" "--relative-to-file" )
>> + ;;
>> +
>> + target)
>> + rootdir="${TARGET_DIR}"
>> + sanitize_extra_args+=( "--no-standard-lib-dirs" "--relative-to-file" )
>
> I thought we decided that target and staging should NOT be relative-to-file,
> but should be absolute paths without rootdir? Or was this a problem for staging,
> because the linker would add the RUNPATH to the library search path and this
> would point to the system libs instead of target libs? According to the man page
> this should only be the case for a native linker, so not for a cross linker.
Grrr, that's wrong, cut an paste error :(. Fixed!
> I don't really like having $ORIGIN-based rpaths in target, but it's no big deal.
>
> Regardless, the reasoning behind the choice we make should be documented here
> in comments. So for host, add something to the effect that we always want
> $ORIGIN-based rpaths to make it relocatable. For staging, say that we want it to
> be the same as target. And for target, explain the choice you made.
>
>
>> + while read file ; do
>> + # check if it's an ELF file
>
> Indentation is inconsistent: sometimes 4 spaces, sometimes 2 spaces (inside the
That's due to 8 spaces replaced by one tab.
> case, and in the condition below). And here, you're switching from spaces to tabs!
I use the default indention from emacs "Shell-script[bash]" which is
usually not a bad choice. I'm going to replace all tabs with spaces.
>> + if ${PATCHELF} --print-rpath "${file}" > /dev/null 2>&1; then
>
> It might be good to check if the file actually has a non-empty rpath. When
> processing a second time, most rpaths are empty so they can be skipped.
I already tried that. It will make the check slower, meaning it costs
more that calling patchelf a second time.
> Maybe even add another patch to patchelf to exit early and quietly with just 0
> or 1 depending on rpath presence.
Optimization of the execution time needs more careful analysis. I have a
patchelf patch which just open and reads the patchelf header to check
quickly if it's an ELF file. But that does not help a lot. readelf is
still faster and I guess that's because it's written in C (and not C++).
Wolfgang.
More information about the buildroot
mailing list