[Buildroot] [PATCH v4 03/11] support/scripts: add fix-rpath script to sanitize the rpath

Wolfgang Grandegger wg at grandegger.com
Tue Jul 4 12:36:13 UTC 2017


Hello,

Am 04.07.2017 um 14:15 schrieb Arnout Vandecappelle:
>   Since you're going to revert to this v4, I'm going to add a few comments here.

Yes, that's what doing now...

> On 27-06-17 12:26, 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>
>> ---
>>   support/scripts/fix-rpath | 112 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 112 insertions(+)
>>   create mode 100755 support/scripts/fix-rpath
>>
>> diff --git a/support/scripts/fix-rpath b/support/scripts/fix-rpath
>> new file mode 100755
>> index 0000000..5d40657
>> --- /dev/null
>> +++ b/support/scripts/fix-rpath
>> @@ -0,0 +1,112 @@
>> +#!/usr/bin/env bash
>> +
>> +# Copyright (C) 2016 Samuel Martin <s.martin49 at gmail.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-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/usr/bin/patchelf)
>> +EOF
>> +}
>> +
>> +: ${PATCHELF:=${HOST_DIR}/usr/bin/patchelf}
>> +
>> +main() {
>> +    local rootdir
>> +    local tree="${1}"
>> +    local find_args=( )
>> +    local sanitize_extra_args=( )
>> +
>> +    case "${tree}" in
>> +	host)
> 
>   Since now you need all this find stuff, my earlier suggestion to not pass the
> tree as an argument is no longer valid.

I didn't change it so far.

> 
>> +	    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" )
>> +
>> +	    # ELF files should not be in these sub-directories
>> +	    find_args+=( "-path" "${STAGING_DIR}/usr/share/terminfo" "-prune" "-o" )
> 
>   I don't understand how this can be needed, since STAGING_DIR is already pruned
> above.

That's wrong here. But there are many files in both, the host and 
staging tree:

$ find host/usr/share/terminfo/ -type f | wc -l
2616
$ find  host/usr/x86_64-buildroot-linux-gnu/sysroot/usr/share/terminfo/ 
share/terminfo/ -type f | wc -l
2616

> 
>> +
>> +	    # 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}"
>> +	    # supress include files
>> +	    find_args+=( "-path" "${STAGING_DIR}/usr/include" "-prune" "-o" )
> 
>   Perhaps it's better to define a variable with all the paths we want to exclude
> - we may want to add more. OTOH, we can do that whenever we indeed do add more.

But it's not just a variable, I need the leading -path and the trailing 
-prune for each dir exclude.

>> +	    sanitize_extra_args+=( "--no-standard-lib-dirs" "--relative-to-file" )
>> +	    ;;
>> +
>> +	target)
>> +	    rootdir="${TARGET_DIR}"
>> +	    sanitize_extra_args+=( "--no-standard-lib-dirs" )
>> +	    ;;
>> +
>> +	*)
>> +	    usage
>> +	    exit 1
>> +	    ;;
>> +    esac
>> +
>> +    find_args+=( "-type" "f" "-print" )
>> +
>> +    while read file ; do
>> +	# check if it's an ELF file
>> +	if ${PATCHELF} --print-rpath "${file}" > /dev/null 2>&1; then
> 
>   Wasn't "readelf -d ${file} | grep DT_RUNPATH" faster? You did some experiments
> a while ago but I forgot what the conclusions were.

There could also be DT_RPATH? But a grep for RPATH should fix that. I 
didn't test that, because I thought that pining is slower anyway. 
Without "grep DT_RUNPATH" it's faster but it will succeed then on 
non-dynamic ELF files as well. We could also tune patchelf to return 
faster if it's not an ELF file. I will remeasure with the command above.

Wolfgang.


More information about the buildroot mailing list