Есть ли способ с открытым исходным кодом сделать статический из динамического исполняемого файла без доступности исходного кода?
Позвольте мне объяснить проблему на примере. В своей повседневной работе я использую какую-то старую программу, например, xfig и pdfedit.
Теперь эти программы довольно старые и не обновляются слишком часто; Я боюсь, что в один прекрасный день они больше не будут работать из-за отсутствия какой-либо библиотеки или несовместимого обновления.
Если программу легко скомпилировать сейчас, на работающей системе решение пригодится: попытайтесь немного взломать исходный код и скомпилировать его статически - полученный исполняемый файл будет большим и не очень эффективным, но он будет работать для обозримое будущее (1). Это похоже на случай xfig
и я попробую это как можно скорее.
Но, например, pdfedit
зависит от Qt3, и настройка системы для ее компиляции в настоящее время довольно сложна. К счастью, его можно запустить прямо сейчас, благодаря тому, что нужная ему библиотека ни с чем не конфликтует. Но это может измениться в будущем, поэтому я хотел бы решить эту проблему:
Как я могу создать статический двоичный файл (или аналогичный объект), если у меня есть динамическая и все библиотеки, но нет исходного кода в Ubuntu?
Я искал вокруг. Одна возможность - statifier(2), но у него много проблем с рандомизацией адресов, так что это нет-нет. Несвободная версия, Ermine, похоже, работает, но я бы действительно предпочел вариант с открытым исходным кодом.
Другая возможность - использовать докер или аналогичную упаковочную систему. Но все учебники, которые я нашел, довольно ориентированы на RedHat; и, честно говоря, довольно сложный для подражания.
Сноски:
(1) не так сумасшедший. Я использую статический ffmpeg, например, работает нормально и без проблем совместимости...
(2) для компиляции statifier
см. https://stackoverflow.com/questions/23498237/compile-program-for-32bit-on-64bit-linux-os-causes-fatal-error
4 ответа
Вы можете решить свою проблему другим, более простым способом:
использование 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/
, Но это применимо к общесистемным изменениям.
Я написал на основе идеи Клауса Д.
Вы можете использовать его следующим образом:
~ # 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"
Opensource mkblob может сделать новый двоичный исполняемый файл, который включает в себя все зависимости ваши потребности программы, и вы будете иметь возможность распространять его другим (и позднее) распределений, чем тот, что был составлен на. Это немного похоже на Statifier и Ermine, о которых упоминалось.
Одно предложение относительно стабилизатора:
Если рандомизация размещения адресного пространства (ASLR) приводит к сбою, вам не нужно отключать его для всей машины. Вы можете отключить его только для этого процесса:
$ setarch `uname -m` -R statified_pdfedit [args...]
Он запустит эту команду с отключенным рандомизированным макетом (не нужно быть пользователем root).