Когда / Как Linux загружает разделяемые библиотеки в адресное пространство? - PullRequest
37 голосов
/ 27 февраля 2011

У меня такой вопрос:

Когда в программах указывается адрес общих объектов?Во время ссылки?Загрузка?Если бы я хотел найти адрес памяти команды system внутри libc внутри моей программы, я мог бы легко найти его в gdb, но что, если я не хочу выводить программу в отладчик?

Может ли этот адрес меняться от запуска к запуску?Существуют ли какие-либо другие инструменты статического анализа, которые позволят увидеть, где библиотеки или функции будут загружены в область памяти этой программы при запуске?objdump для сбора информации)

Ответы [ 5 ]

64 голосов
/ 27 февраля 2011

Библиотеки загружаются с помощью ld.so (динамический компоновщик или компоновщик времени выполнения aka rtld, ld-linux.so.2 или ld-linux.so.* в случае Linux; часть glibc).Он объявляется как «интерпретатор» (раздел INTERP; .interp) всех двоичных файлов ELF с динамической связью.Итак, когда вы запускаете программу, Linux запускает ld.so (загрузка в память и переход к точке входа), затем ld.so загружает вашу программу в память, подготавливает ее и затем запускает.Вы также можете запустить динамическую программу с помощью

 /lib/ld-linux.so.2 ./your_program your_prog_params

ld.so, выполняющей фактические open и mmap всех необходимых файлов ELF, как файла ELF вашей программы, так и файлов ELF всех необходимых библиотек.Кроме того, он заполняет таблицы GOT и PLT и разрешает перемещения (он записывает адреса функций из библиотек на сайты вызовов, во многих случаях с косвенными вызовами).

Типичный адрес загрузки некоторой библиотеки, которую вы можете получить с помощью ldd утилита.На самом деле это скрипт bash, который устанавливает переменную среды отладки ld.so (на самом деле LD_TRACE_LOADED_OBJECTS=1 в случае rtld для glibc) и запускает программу.Вы даже можете сделать это самостоятельно без использования скрипта, например, используя bash, легко изменяя переменные окружения для одного запуска:

 LD_TRACE_LOADED_OBJECTS=1 /bin/echo

ld.so увидит эту переменную и разрешит все необходимые библиотеки ивывести загрузочные адреса из них.Но с этим набором переменных ld.so фактически не запустит программу (не уверен насчет статических конструкторов программы или библиотек).Если функция ASLR отключена, адрес загрузки будет в большинстве случаев одинаковым.В современных Linux-системах часто включается ASLR, поэтому для его отключения используйте echo 0 | sudo tee /proc/sys/kernel/randomize_va_space.

. Вы можете найти смещение функции system внутри утилиты libc.so с nm из binutils.,Я думаю, вы должны использовать nm -D /lib/libc.so или objdump -T /lib/libc.so и вывод grep.

13 голосов
/ 27 февраля 2011

«Идите прямо к источнику и спросите коня ...»

Drepper - Как писать общие библиотеки

Обязательно прочитайте документацию для авторов библиотек Linux. Объясняет механику загрузки в некоторых деталях.

8 голосов
/ 27 февраля 2011

Команда nm, используемая на libc.so, покажет вам местоположение символа system в libc.so.Однако, если ASLR включен, адрес libc.so загружается по адресу, и, таким образом, конечный адрес system будет меняться случайным образом при каждом запуске вашей программы.Даже без ASLR вам необходимо определить адрес, по которому libc.so загружается, и сместить адрес system на эту величину.

6 голосов
/ 27 февраля 2011

Если вы просто хотите получить адрес функции, не задавая название, вы можете dlopen() основная программа:

void *self = dlopen(NULL, RTLD_NOW);
dlsym(self, "system"); // returns the pointer to the system() function

Если вам нужен только адрес функции, имя которой вы знаете во время компиляции, просто используйте void *addr = &system;

0 голосов
/ 27 февраля 2011

Я бы рекомендовал, чтобы в вашей среде был путь LD_LIBRARY_PATH. Это определяет, где находятся общие библиотеки. Вам также может понадобиться заглянуть в /etc/ld.so.conf Посмотрите на это сообщение http://www.google.com/url?sa=t&source=web&cd=3&ved=0CCQQFjAC&url=http%3A%2F%2Fubuntuforums.org%2Fshowthread.php%3Ft%3D324660&ei=KqJpTey7JofEsAPE9_imBA&usg=AFQjCNEIbGGrTHp4fufRuj4Yfc58RTHcag&sig2=_9tdlyadMbPc-FcOdCko-w

...