Как создать статически связанную позицию независимого исполняемого файла ELF в Linux? - PullRequest
3 голосов

У меня есть независимое рабочее место Linux x86_64 hello world:

main.S

.text
.global _start
_start:
asm_main_after_prologue:
    /* Write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    lea msg(%rip), %rsi  /* buffer */
    mov $len, %rdx  /* len */
    syscall

    /* Exit */
    mov $60, %rax   /* syscall number */
    mov $0, %rdi    /* exit status */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

, который я могу собрать и запустить с:

as -o main.o main.S
ld -o main.out main.o
./main.out

Поскольку он не зависит от позиции из-за относительной нагрузки RIP , теперь я хотел связать его как PIE и посмотреть, как он загружается по случайным адресам каждый раз , чтобы повеселиться.

Сначала я попытался:

ld -pie -o main.out main.o

, но затем запустить его не удалось с помощью:

-bash: ./main.out: No such file or directory

и readelf -Wa говорит, что вместо странного интерпретатора /lib/ld64.so.1 использовался вместообычный /lib64/ld-linux-x86-64.so.2 по какой-то причине.

Затем я узнал, что он на самом деле является рекомендуемым System V AMD64 ABI именем интерпретатора в 5.2.1 "Program Interpreter".

В любом случае, я тогда пытаюсь вызвать вопросы с помощью:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o main.out main.o

, и теперь это работает: я получаю hello, и исполняемый файл каждый раз загружается на другой адрес в соответствии с GDB.

Наконец, в качестве последнего шага я хотел также сделать этот исполняемый файл статически связным.чтобы сделать вещи еще более минимальными и, возможно, избавиться от явного -dynamic-linker.

Вот чего я не мог сделать, и вот почему я спрашиваю здесь.

Если япопробуйте любой из:

ld -static -pie -o main.out main.o
ld -static -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o main.out main.o

-static, кажется, не имеет никакого значения: я все еще получаю динамические исполняемые файлы .

После быстрого просмотра исходного кода ядра 5.0код в fs / binfmt_elf.c Я увидел этот интересный комментарий:

         * There are effectively two types of ET_DYN
         * binaries: programs (i.e. PIE: ET_DYN with INTERP)
         * and loaders (ET_DYN without INTERP, since they
         * _are_ the ELF interpreter). The loaders must

, поэтому я думаю, что когда я добьюсь того, чего хочу, у меня будет действительный переводчик, и я такЯ собираюсь использовать свой собственный минимальный hello world в качестве интерпретатора другой программы.

Одна вещь, которую я мог бы попробовать позже, это посмотреть, как какая-то реализация libc компилирует свой загрузчик и копирует его.

Связанный вопрос: Компилировать независимый от позиции исполняемый файл со статически связанной библиотекой на 64-битной машине , но в нем упоминается внешняя библиотека, поэтому, надеюсь, это более минималистично и ответственно.

Проверено в Ubuntu 18.10.

1 Ответ

2 голосов
/ 13 апреля 2019

Вы хотите добавить --no-dynamic-linker к вашей команде ссылки:

$ ld main.o -o main.out -pie --no-dynamic-linker

$ file main.out
main.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped

$ ./main.out
hello

, поэтому я предполагаю, что когда я добьюсь того, чего хочу, у меня будет действительный переводчик, и я собираюсьиспользовать свой собственный минимальный привет-мир в качестве переводчика другой программы.

Я не уверен, что правильно понял, что вы говорите.Если вы имели в виду, что main.out будет иметь себя в качестве интерпретатора, это неправильно.

PS GLIBC-2.27 добавлена ​​поддержка для -static-pie, поэтому вам больше не придется прибегать к сборке вполучить статически связанный двоичный файл пирога.Но вам придется использовать самые последние GCC и GLIBC.

...