packelf/packelf.sh

154 lines
4.1 KiB
Bash
Raw Normal View History

2024-05-20 20:57:31 +02:00
#!/usr/bin/env sh
#set -o pipefail # bash extension
set -e
2022-10-05 04:46:42 +02:00
2024-05-20 20:57:31 +02:00
# These vars will be modified automatically with sed
run_mode=packer
compress_flag=-z
program=
ld_so=
load() {
script_path="$0"
while link_path=$(readlink "$script_path"); do
script_path="$link_path"
done
unpack_dir=$(dirname "$script_path")
exec "$unpack_dir/$program.res/$ld_so" \
--library-path "$unpack_dir/$program.res" \
"$unpack_dir/$program.res/$program" "$@"
# unreachable
2022-10-05 04:46:42 +02:00
}
2024-05-20 20:57:31 +02:00
if [ "$run_mode" = loader ]; then
load "$@"
2022-10-05 04:46:42 +02:00
fi
2024-05-20 20:57:31 +02:00
pack_help() {
echo "Usage: $0 [-zjJn] <ELF_SRC_PATH> <DST_PATH> [ADDITIONAL_LIBS ...]"
echo " -zjJ compress flag passed to tar, '-z' by default"
echo " -n pack without compress"
}
pack() {
[ $# -ge 2 ] || {
pack_help
exit 1
}
case $1 in
-z|-j|-J)
compress_flag=$1
shift
;;
-n)
compress_flag=''
shift
;;
-h|--help)
pack_help
exit 0
;;
*)
;;
esac
src="$1"
shift
dst="$1"
shift
libs="$(ldd "$src" | grep -F '/' | sed -E 's|[^/]*/([^ ]+).*?|/\1|')"
2024-06-23 22:50:17 +02:00
ld_so="$(echo "$libs" | grep -F '/ld-linux-' || echo "$libs" | grep -F '/ld-musl-' || echo "$libs" | grep -F '/ld.so')"
2024-05-20 20:57:31 +02:00
ld_so="$(basename "$ld_so")"
program="$(basename "$src")"
cat "$0" | sed -E \
-e 's/^run_mode=[^ ]*$/run_mode=unpacker/' \
-e 's/^compress_flag=[^ ]*$/compress_flag='"$compress_flag"'/' \
-e 's/^program=[^ ]*$/program='"$program"'/' \
-e 's/^ld_so=[^ ]*$/ld_so='"$ld_so"'/' \
>"$dst"
2024-06-23 20:47:12 +02:00
echo "Creating static executable $dst from $src"
for libraries in ${libs} ; do
echo "Linking library ${libraries}"
done
echo "Creating executable linker"
echo "Building static executable in $dst"
tar $compress_flag -ch --transform 's@.*/@'"$program"'.res/@' "$src" $libs "$@" >>"$dst"
2024-05-20 20:57:31 +02:00
chmod +x "$dst"
2024-06-23 20:47:12 +02:00
echo "Created successfully"
#echo "'$src' was packed to '$dst'"
echo ""
2024-05-20 20:57:31 +02:00
echo "$dst" | grep -q / || dst="./$dst"
2024-06-23 20:47:12 +02:00
echo "Just run '$dst <ARGS>' to execute the command."
2024-05-20 20:57:31 +02:00
echo "Or run 'PACKELF_UNPACK_DIR=xxx $dst' to unpack it only."
}
unpack() {
if [ -n "$PACKELF_UNPACK_DIR" ]; then
[ -d "$PACKELF_UNPACK_DIR" ] || {
echo "'$PACKELF_UNPACK_DIR' is not a dir."
exit 1
}
[ -e "$PACKELF_UNPACK_DIR/$program" ] && {
echo "'$PACKELF_UNPACK_DIR/$program' already exists, please remove it first."
exit 1
}
unpack_dir="$PACKELF_UNPACK_DIR"
else
if [ -n "$PACKELF_TMP_DIR" ]; then
unpack_dir="$PACKELF_TMP_DIR"
else
tmp_parent=/tmp
2024-05-20 20:57:31 +02:00
mkdir -p "$tmp_parent"
unpack_dir=$(mktemp -d -p "$tmp_parent" || echo "$tmp_parent")
fi
trap 'rm -rf "$unpack_dir"' 0 1 2 3 6 10 12 13 14 15
fi
check_path="$unpack_dir/__check_permission__"
if ! (echo > "$check_path" && chmod +x "$check_path" && [ -x "$check_path" ]); then
rm -rf "$unpack_dir"
tmp_parent="$(pwd)/packelf_tmp"
mkdir -p "$tmp_parent"
unpack_dir="$(mktemp -d -p "$tmp_parent" || echo "$tmp_parent")"
fi
sed '1,/^#__END__$/d' "$0" | tar $compress_flag -x -C "$unpack_dir"
sed -i 's@/etc/ld.so.preload@/etc/___so.preload@g' "$unpack_dir/$program.res/$ld_so"
if [ -n "$PACKELF_UNPACK_DIR" ]; then
sed '/^#__END__$/,$d' "$0" > "$unpack_dir/$program"
sed -i -E 's/^run_mode=\w*$/run_mode=loader/' "$unpack_dir/$program"
chmod +x "$unpack_dir/$program"
2024-06-05 18:02:53 +02:00
rm -f "$check_path"
2024-05-20 20:57:31 +02:00
echo "'$program' was unpacked to '$unpack_dir'."
echo "$unpack_dir" | grep -q / || unpack_dir="./$unpack_dir"
echo "You can run '$unpack_dir/$program ARGS...' to execute the command."
else
"$unpack_dir/$program.res/$ld_so" \
--library-path "$unpack_dir/$program.res" \
"$unpack_dir/$program.res/$program" "$@"
exit $?
fi
}
if [ "$run_mode" = unpacker ]; then
unpack "$@"
else
pack "$@"
fi
exit 0
#__END__