]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/commitdiff
icecc-create-env: Fix executable rpaths
authorJoshua Watt <jpewhacker@gmail.com>
Mon, 12 Feb 2018 16:52:04 +0000 (10:52 -0600)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Thu, 15 Feb 2018 13:20:27 +0000 (13:20 +0000)
Executables in the toolchain archive occasionally contain runtime
library search paths (RPATH) that use the $ORIGIN placeholder. However,
in order for that placeholder to work, /proc must be mounted. When
iceccd executes the toolchain in the chroot environment, it doesn't
mount /proc, so it is unable to resolve $ORIGIN resulting in a failure
to find dynamic libraries.

The fix is to replace $ORIGIN in executable RPATH entries with the known
chroot executable path. In order for this to work, the actual real path
to the executable must be resolved to remove any symlinks, otherwise the
calculate $ORIGIN replacement will be wrong. This is done by using
"readlink -f", which is an acceptable dependency because Yocto already
requires it.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
meta/recipes-devtools/icecc-create-env/icecc-create-env/icecc-create-env

index 426b093d91c05c9a4d07b3ab9a24ea840beb4587..90d249df9f351bb4cd76d38eb6503a58d1901af2 100755 (executable)
@@ -12,6 +12,26 @@ is_dynamic_elf ()
     (file -L "$1" | grep 'ELF' > /dev/null 2>&1) && (! file -L "$1" | grep 'static' > /dev/null 2>&1)
 }
 
+fix_rpath ()
+{
+    # Patches the RPATH for a file. When the program is executed in the chroot
+    # be iceccd, /proc is not mounted. As such, $ORIGIN can't be resolved. To
+    # work around this, replace all instances of $ORIGIN in RPATH with the
+    # known chroot path to the executables directory
+    local path="$1"
+    local origin="$2"
+    if ! is_dynamic_elf "$path"; then
+        return
+    fi
+    local new_rpath="`readelf -w -d "$path" | grep RPATH | \
+        sed 's/.*\[\(.*\)\]/\1/g' | \
+        sed "s,\\\$ORIGIN,/$origin,g"`"
+
+    if test -n "$new_rpath"; then
+        $PATCHELF --set-rpath "$new_rpath" "$path"
+    fi
+}
+
 is_contained ()
 {
     case " $target_files " in
@@ -47,9 +67,8 @@ add_file ()
         name="$2"
     fi
     test -z "$name" && return
-    # ls -H isn't really the same as readlink, but
-    # readlink is not portable enough.
-    path=`ls -H $path`
+    # readlink is required for Yocto, so we can use it
+    path=`readlink -f "$path"`
     toadd="$name=$path"
     is_contained "$toadd" && return
     if test -z "$silent"; then
@@ -108,6 +127,17 @@ added_as=$1
 shift
 archive_name=$1
 
+if test -z "$PATCHELF"; then
+    PATCHELF=`which patchelf 2> /dev/null`
+fi
+if test -z "$PATCHELF"; then
+    PATCHELF=`which patchelf-uninative 2> /dev/null`
+fi
+if test -z "$PATCHELF"; then
+    echo "patchelf is required"
+    exit 1
+fi
+
 if test -z "$added_gcc" || test -z "$added_gxx" ; then
     echo "usage: $0 <gcc_path> <g++_path>"
     exit 1
@@ -197,6 +227,8 @@ for i in $target_files; do
         if test -f $tempdir/$target -a -x $tempdir/$target; then
             strip -s $tempdir/$target 2>/dev/null
         fi
+
+        fix_rpath $tempdir/$target `dirname $target`
     else
         mkdir -p $tempdir/`dirname $path`
         cp -pH $path $tempdir/$path
@@ -210,6 +242,8 @@ for i in $target_files; do
             strip -s $tempdir/$path 2>/dev/null
         fi
 
+        fix_rpath $tempdir/$path `dirname $path`
+
         path=`echo $path | cut -b2-`
         new_target_files="$new_target_files $path"
     fi