是否有任何开源方法可以从没有源代码的动态可执行文件创建静态文件?

是否有任何开源方法可以从没有源代码的动态可执行文件创建静态文件?

让我用一个例子来解释这个问题。我在日常工作中使用一些旧程序,例如韓國pdf编辑

现在,这些程序已经很老了,而且更新也不频繁;我担心有一天它们会因为缺少某些库或不兼容的更新而不再工作。

如果程序很容易编译现在在运行的系统上,解决方案很方便:尝试对源代码进行一些修改并静态编译 --- 生成的可执行文件会很大而且效率不高,但它在可预见的未来会有效(1)。这似乎是这种情况,xfig我会尽快尝试。

但是,例如,pdfedit依赖于 Qt3,并且此时设置系统来编译它相当复杂。幸运的是它可以运行目前,由于它所需的库不与任何库冲突,因此可以解决这个问题。但是这种情况将来可能会发生变化,因此我想解决这个问题:

如果我在 Ubuntu 上有一个动态二进制文件和所有库,但没有源代码,我该如何制作静态二进制文件(或类似的东西)?

我搜索了一下。一种可能是定势器(2),但它有很多地址随机化的问题,所以这是不行的。非免费版本,,似乎可行,但我真的更喜欢开源选项。

另一种可能性是使用docker或类似的打包系统。但所有的我发现的教程都是以 RedHat 为导向的;而且说实话,理解起来相当复杂。


脚注

(1)不是那么疯狂。我用的是静态 ffmpeg例如,运行正常并且没有任何兼容性问题......

(2)编译statifier,参见https://stackoverflow.com/questions/23498237/compile-program-for-32bit-on-64bit-linux-os-causes-fatal-error

答案1

您可以通过另一种更简单的方法解决您的问题:

使用ldd你的可执行文件来查看链接的库,例如:

$ ldd /bin/bash
linux-vdso.so.1 =>  (0x00007fffb2fd4000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fac9ef91000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fac9ed8d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fac9e9c6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fac9f1e1000)

然后将所有库收集到一个文件夹中,并在运行程序之前设置 LD_LIBRARY_PATH 环境变量以指向该文件夹:

$ LD_LIBRARY_PATH="/opt/my_program/lib" /opt/my_program/start

或者,您可以将 lib 文件夹的条目添加到/etc/ld.so.conf.d/。但这将使更改应用于整个系统。

答案2

开源可以制作一个新的二进制可执行文件,其中包含程序所需的所有依赖项,并且您可以将其分发到编译它时所在的发行版以外的其他发行版(也包括更高版本)。它的工作原理有点像之前提到的 Statifier 和 Ermine。

答案3

我写打包工具基于Klaus D的想法。

你可以像这样使用它:

~ # packelf.sh `which perf` /root/perf
~ # /root/perf --version
perf version 3.10.0-1160.49.1.el7.x86_64.debug

打包工具

#!/bin/bash
set -eo pipefail

[ $# -lt 2 ] && {
    echo "usage: $0 <ELF_SRC_PATH> <DST_PATH> [ADDITIONAL_LIBS ...]"
    exit 1
}

src="$1"
dst="$2"
shift
shift

cat >"$dst" <<EOF
#!/bin/bash
tmp_dir="\$(mktemp -d)"
check_path="\$tmp_dir/__check_permission__"
trap 'rm -rf \$tmp_dir' 0 1 2 3 6
if ! (touch "\$check_path" && chmod +x "\$check_path" && [ -x "\$check_path" ]); then
    rm -rf "\$tmp_dir"
    tmp_dir="\$(TMPDIR="\$(pwd)" mktemp -d)"
fi
sed '1,/^#__END__$/d' "\$0" | tar -xz -C "\$tmp_dir"
"\$tmp_dir/LD_SO" --library-path "\$tmp_dir" "\$tmp_dir/PROGRAM" "\$@"
exit \$?
#__END__
EOF

libs="$(ldd "$src" | grep -F '/' | sed -E 's|[^/]*/([^ ]+).*?|/\1|')"
ld_so="$(echo "$libs" | grep -F '/ld-linux-')"
sed -E -i -e 's|PROGRAM|'"$(basename "$src")"'|' -e 's|LD_SO|'"$(basename "$ld_so")"'|' "$dst"
tar -czh --transform 's/.*\///g' "$src" $libs "$@" >>"$dst" 2> >(grep -v 'Removing leading' >&2)
chmod +x "$dst"

答案4

关于的一个建议定势器

如果地址空间布局随机化 (ASLR) 导致其失败,则不必为整个机器关闭它。您可以仅为该过程关闭它:

$ setarch `uname -m` -R statified_pdfedit [args...]

它将在禁用随机布局的情况下运行该命令(无需root)。

相关内容