Как получить места в памяти функций библиотеки? - PullRequest
2 голосов
/ 31 марта 2009

Я компилирую программу на Си с помощью компилятора SPARC RTEMS C.

Используя опцию Xlinker -M, я могу получить большую карту памяти с множеством вещей, которые я не узнаю.

Я также пытался использовать утилиту RCC nm, которая возвращает чуть более читаемую таблицу символов. Я предполагаю, что местоположение, указанное этой утилитой для, скажем, printf, является местоположением, где printf находится в памяти, и что каждая программа, которая вызывает printf, достигнет этого местоположения во время выполнения. Это правильное предположение?

Есть ли способ получить список мест для всех функций библиотеки / системы? Кроме того, когда соединение установлено, оно связывает только те функции, которые вызывает исполняемый файл, или это все функции в библиотеке? Мне кажется, что это последнее, учитывая количество вещей, которые я нашел в таблице символов и карте памяти. Могу ли я сделать так, чтобы он связывал только необходимые функции?

Спасибо за вашу помощь.

Ответы [ 3 ]

4 голосов
/ 31 марта 2009

Чаще всего при использовании динамической библиотеки утилита nm не сможет дать вам точный ответ. Двоичные файлы в наши дни используют так называемые перемещаемые адреса. Эти адреса изменяются, когда они отображаются в адресное пространство процесса.

Используя опцию Xlinker -M, я могу получить большую карту памяти с множеством вещей, которые я не узнаю.

Карта компоновщика обычно содержит все символы - ваш, стандартные библиотеки, хуки времени выполнения и т. Д.

Есть ли способ получить список мест для всех функций библиотеки / системы?

Заголовки - хорошее место для поиска.

Кроме того, когда соединение установлено, оно связывает только те функции, которые вызывает исполняемый файл, или это все функции в библиотеке?

Связывание не обязательно означает, что все символы будут разрешены (т. Е. Указан адрес). Это зависит от типа создаваемого вами двоичного файла.

Однако некоторые компиляторы, такие как gcc, позволяют вам создавать не перемещаемый двоичный файл или нет. (Для gcc вы можете проверить файлы exp, dlltool и т. Д.) Проверьте с соответствующей документацией.

1 голос
/ 17 мая 2009

Если вы хотите динамически связать, вы используете dlopen / dlsym для разрешения точек входа в общую библиотеку UNIX .so.

http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html

Предполагая, что вы знаете имена функций, которые вы хотите вызвать, и какие они есть. Так что это довольно просто.

void    *handle;
int     *iptr, (*fptr)(int);

/* open the needed object */
handle = dlopen("/usr/home/me/libfoo.so", RTLD_LOCAL | RTLD_LAZY);

/* find the address of function and data objects */
*(void **)(&fptr) = dlsym(handle, "my_function");
iptr = (int *)dlsym(handle, "my_object");

/* invoke function, passing value of integer as a parameter */
(*fptr)(*iptr);

Если вы хотите получить список всех динамических символов, лучше всего использовать objdump -T file.so. (objdump -t file.a, если вы ищете статически связанные функции). Objdump является кроссплатформенным, частью binutils, поэтому в крайнем случае вы можете скопировать ваши двоичные файлы в другую систему и связать их с objdump на другой платформе.

Если вы хотите, чтобы динамическое связывание было оптимальным, вы должны взглянуть на ваш ld.so.conf, в котором указан порядок поиска для ld.so.cache (so.cache right;).

1 голос
/ 01 апреля 2009

с динамическим связыванием, 1. Ваш исполняемый файл имеет специальное место для всех внешних вызовов (таблица PLT). 2. у вашего исполняемого файла есть список библиотек, от которых зависит

Эти две вещи независимы. Невозможно сказать, какая внешняя функция находится в какой библиотеке.

Когда программа выполняет внешний вызов функции, то, что на самом деле происходит, вызывает запись в таблице PLT, которая выполняет переход в динамический загрузчик. Динамический загрузчик ищет, какая функция была вызвана (через PLT), ищет ее имя (через таблицу символов в исполняемом файле) и ищет это имя во ВСЕХ библиотеках, которые отображаются (все, от чего зависит данный исполняемый файл). Как только имя найдено, адрес соответствующей функции записывается обратно на PLT, поэтому в следующий раз вызов будет выполнен в обход динамического компоновщика.

Чтобы ответить на ваш вопрос, вы должны выполнить ту же работу, что и динамический компоновщик: получить список зависимых библиотек и найти все имена в них. Это можно сделать с помощью утилиты 'nm' или 'readelf'.

Что касается статической связи, я думаю, что все символы в данном объектном файле в libXXX.a связаны друг с другом. Например, статическая библиотека libXXX.a состоит из объектных файлов a.o, b.o и c.o. Если вам нужна функция foo (), и она находится в a.o, то a.o будет связана с вашим приложением - вместе с функцией foo () и всеми другими данными, определенными в ней. По этой причине, например, функции библиотеки C разбиты на файлы.

...