./unlink path/to/binary
out/run to call it
| #!/bin/bash | |
| set -e | |
| set -u | |
| set -o pipefail | |
| ELF=$1 | |
| TGT=$PWD/${2:-out} | |
| rm -rf "$TGT" | |
| mkdir -p "$TGT" | |
| interpreter=$(readelf -l "$ELF" | grep "Requesting program interpreter") | |
| interpreter=${interpreter#*[:]} | |
| interpreter=${interpreter:1} | |
| interpreter=${interpreter::-1} | |
| resolveelf() { | |
| local lib | |
| local needed | |
| mapfile -t needed <<<"$(readelf -d "$1" | grep "(NEEDED)" | sed -r 's/.*\[(.*)\]/\1/')" | |
| for lib in "${needed[@]}"; do | |
| if [ -z "$lib" ]; then | |
| continue | |
| fi | |
| echo "-> $lib" | |
| libname=$(basename "$lib") | |
| if [ "$libname" = "$(basename "$interpreter")" ]; then | |
| continue | |
| fi | |
| if [ -f "$TGT/$lib" ]; then | |
| continue | |
| fi | |
| if ! [ -f "$lib" ]; then | |
| # relative path | |
| lib=$(ldconfig -p | grep -F "$lib" | head -1) | |
| lib=${lib//* => /} | |
| if ! [ "$libname" = "$(basename "$lib")" ]; then | |
| echo "library name mismatch: $libname -> $lib" # happens with version mismatch, don't know how to handle this | |
| lib="$(dirname "$lib")/$libname" | |
| fi | |
| fi | |
| resolveelf "$lib" | |
| done | |
| cp "$1" "$TGT" | |
| echo "patching $1" | |
| for lib in "${needed[@]}"; do | |
| patchelf --replace-needed "$lib" "./$(basename "$lib")" "$TGT/$(basename "$1")" | |
| done | |
| } | |
| resolveelf "$ELF" | |
| cp "$interpreter" "$TGT" | |
| patchelf --set-interpreter "./$(basename "$interpreter")" "$TGT/$(basename "$ELF")" | |
| cat <<EOF >"$TGT/run" | |
| #!/bin/sh | |
| cd "\$(dirname "\$0")" | |
| exec "$(basename "$ELF")" "\$@" | |
| EOF | |
| chmod +x "$TGT/run" |