2009-03-31 2 views
2

Я компилирую программу C с компилятором SPARC RTEMS C.Как получить места памяти библиотечных функций?

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

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

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

Благодарим за помощь.

ответ

4

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

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

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

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

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

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

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

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

+0

Если я использую параметр -static для компоновщика, чтобы избежать использования разделяемых библиотек, это позволит избежать проблем, связанных с динамическими библиотеками? – mandaleeka

+0

Какие проблемы? Я предполагаю, что у вас есть повторяющееся определение символа. В этом случае нет. Вы должны скрыть/переименовать, чтобы избежать столкновения имени. – dirkgently

+0

Извините, я имел в виду, что nm даст мне точный ответ или адрес по-прежнему перемещается? – mandaleeka

1

С динамическим связыванием 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 разбиты на один файл.

1

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

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

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

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, поэтому в крайнем случае вы можете скопировать ваши двоичные файлы в другую систему и interrorgate их с objdump на другой платформе.

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

Смежные вопросы