Как компоновщик Dynami c выполняет / proc / self / exe - PullRequest
1 голос
/ 08 мая 2020

При выполнении динамически связанного исполняемого файла на Linux компоновщик динамического c вызывается как его интерпретатор (описанный в этом ответе ). Если я правильно понимаю, запуск:

$ ./dynamic_elf

приведет к выполнению Linux:

/lib64/ld-linux.so.2 ./dynamic_elf

Мне трудно понять, как это будет работать для /proc/self/exe. Согласно logi c выше, выполнение:

$ /proc/self/exe

приведет к выполнению Linux:

/lib64/ld-linux.so.2 /proc/self/exe

Теперь, когда компоновщик Dynami c пытается загрузить эльфа at /proc/self/exe, разве это не указывает на сам компоновщик Dynami c, поскольку ld-linux.so.2 теперь является исполняемым файлом?

Я знаю, что команда выше JustWorks, так что мне не хватает?

  • Получает ли компоновщик Dynami c больше, чем путь вызвавшего его эльфа?

  • Отличается ли здесь семантика от shebang (#!) переводчики?

1 Ответ

2 голосов
/ 08 мая 2020

Как вы отметили, ядро ​​не передает исполняемый двоичный файл в качестве пути к интерпретатору:

$ /lib64/ld-linux-x86-64.so.2 /proc/self/exe
loader cannot load itself

Хотя компоновщик glib c Dynami c поддерживает этот метод вызова (при условии программа для запуска в качестве аргумента), это не то, что используется во время нормального выполнения интерпретируемого двоичного файла ELF. Фактически, ядро ​​предоставляет аргументы от execve в неизмененном виде для компоновщика Dynami c.

Компоновщик Dynami c вообще не «загружает» и не «выполняет» интерпретируемый двоичный файл ELF. Ядро загружает и интерпретатор и интерпретируемый двоичный файл в память и начинает выполнение с точки входа интерпретатора. Точка входа интерпретируемого двоичного файла передается интерпретатору через поле AT_ENTRY во вспомогательном векторе.

Компоновщик динамического c затем выполняет необходимое связывание времени выполнения и переходит к «реальной» точке входа .

Вы можете наблюдать все это в gdb, если вы установите точку останова на _start при выполнении обычного интерпретируемого исполняемого файла ELF. С помощью «show args» вы увидите «настоящий» argv без каких-либо дополнительных значений, а в карте памяти процесса уже будет загружен интерпретируемый двоичный файл (до того, как интерпретатор выполнит одну инструкцию).

#! скрипты работают так, как вы ожидаете (фактически манипулируя значениями argv).

...