Ответ 1
Там CDE немного программного обеспечения, предназначенного для того, чтобы делать именно то, что вы хотите. Здесь говорится об этом в google tech http://www.youtube.com/watch?v=6XdwHo1BWwY
У меня есть двоичный файл Linux, без источников, который работает на одной машине, и я хотел бы сделать автономный пакет, который будет работать на другой машине той же архитектуры. Каков способ достижения этого?
В моем случае обе машины имеют одинаковую архитектуру, то же самое ядро Ubuntu, но на целевом компьютере нет make
и имеет неправильную версию файлов под /lib
и /usr
Одна из моих идей заключалась в использовании chroot
и воссоздании подмножества файловой системы, которое использует двоичный файл, возможно, используя strace
, чтобы выяснить, что ему нужно. Есть ли инструмент, который делает это уже?
Для потомков, здесь, как я выясню, какие файлы открывается процесс
#!/usr/bin/python
# source of trace_fileopen.py
# Runs command and prints all files that have been successfully opened with mode O_RDONLY
# example: trace_fileopen.py ls -l
import re, sys, subprocess, os
if __name__=='__main__':
strace_fn = '/tmp/strace.out'
strace_re = re.compile(r'([^(]+?)\((.*)\)\s*=\s*(\S+?)\s+(.*)$')
cmd = sys.argv[1]
nowhere = open('/dev/null','w')#
p = subprocess.Popen(['strace','-o', strace_fn]+sys.argv[1:], stdout=nowhere, stderr=nowhere)
sts = os.waitpid(p.pid, 0)[1]
output = []
for line in open(strace_fn):
# ignore lines like --- SIGCHLD (Child exited) @ 0 (0) ---
if not strace_re.match(line):
continue
(function,args,returnval,msg) = strace_re.findall(line)[0]
if function=='open' and returnval!='-1':
(fname,mode)=args.split(',',1)
if mode.strip()=='O_RDONLY':
if fname.startswith('"') and fname.endswith('"') and len(fname)>=2:
fname = fname[1:-1]
output.append(fname)
prev_line = ""
for line in sorted(output):
if line==prev_line:
continue
print line
prev_line = line
Обновление
Проблема с решениями LD_LIBRARY_PATH
заключается в том, что /lib
жестко закодирован в интерпретатор и имеет приоритет над LD_LIBRARY_PATH
, поэтому исходные версии сначала загружаются. Интерпретатор жестко закодирован в двоичный файл. Один из подходов может состоять в том, чтобы исправить интерпретатор и запустить двоичный файл как patched_interpreter mycommandline
Проблема заключается в том, что когда mycommandline
начинается с java
, это не работает, потому что Java-настройка LD_LIBRARY_PATH
и перезагружается сама, которая прибегает к старый интерпретатор. Решение, которое сработало для меня, заключалось в том, чтобы открыть двоичный файл в текстовом редакторе, найти интерпретатор (/lib/ld-linux-x86-64.so.2
) и заменить его на путь длины до исправленного интерпретатора
Там CDE немного программного обеспечения, предназначенного для того, чтобы делать именно то, что вы хотите. Здесь говорится об этом в google tech http://www.youtube.com/watch?v=6XdwHo1BWwY
Как уже упоминалось, статическая привязка является одним из вариантов. Кроме того, статическая связь с glibc становится немного более сломанной с каждым выпуском (извините, ссылка отсутствует, просто мой опыт).
Ваша идея chroot
, вероятно, будет излишней.
Решение большинства коммерческих продуктов, насколько я могу судить, заключается в том, чтобы сделать их "приложение" оболочкой script, которая устанавливает LD_LIBRARY_PATH
, а затем запускает фактический исполняемый файл. Что-то в этом роде:
#!/bin/sh
here=`dirname "$0"`
export LD_LIBRARY_PATH="$here"/lib
exec "$here"/bin/my_app "[email protected]"
Затем вы просто выгружаете копию всех соответствующих файлов .so в lib/
, поместите свой исполняемый файл в bin/
, поместите script в .
и отправите все дерево.
(Чтобы быть достойным производства, правильно добавьте "$here"/lib
в LD_LIBRARY_PATH
, если он не пуст и т.д.)
[править, чтобы перейти с обновлением]
Я думаю, вы можете быть смущены тем, что жестко закодировано, а что нет. ld-linux-x86-64.so.2
- сам динамический компоновщик; и вы правы, что его путь жестко закодирован в заголовок ELF. Но другие библиотеки не жестко закодированы; они ищутся динамическим компоновщиком, который будет отмечать LD_LIBRARY_PATH
.
Если вам действительно нужен другой ld-linux.so, вместо исправления заголовка ELF просто запустите динамический компоновщик:
/path/to/my-ld-linux.so my_program <args>
Это будет использовать ваш компоновщик, а не тот, который указан в заголовке ELF.
Исправление самого исполняемого файла является злом. Пожалуйста, подумайте о бедном человеке, который должен поддерживать ваши вещи после вашего продвижения... Никто не ожидает, что вы взломали заголовок ELF вручную. Любой может прочитать, что делает оболочка script.
Только мои $0,02.
Есть почти наверняка лучшие ответы, но вы можете узнать, какие библиотеки нужны двоичным файлам с помощью команды ldd
(пример для двоичного кода ls
):
$ ldd /bin/ls
linux-vdso.so.1 => (0x00007ffffff18000)
librt.so.1 => /lib/librt.so.1 (0x00007f5ae565c000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00007f5ae543e000)
libacl.so.1 => /lib/libacl.so.1 (0x00007f5ae5235000)
libc.so.6 => /lib/libc.so.6 (0x00007f5ae4eb2000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007f5ae4c95000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5ae588b000)
libdl.so.2 => /lib/libdl.so.2 (0x00007f5ae4a90000)
libattr.so.1 => /lib/libattr.so.1 (0x00007f5ae488b000)
После этого вы можете сделать копии и поместить их в соответствующие места на целевой машине.