Как сопоставить символ функции с диапазоном адресов - PullRequest
1 голос
/ 04 марта 2011

Как правильно определить диапазон адресов для символа функции (строки)?Я буду работать со статически связанными, не раздетыми программами на Си в Linux.

Например, я хотел бы сделать что-то вроде этого:

char* func_name = get_string_from_user();
printf("start address: %p \n", get_addr_range(func_name).start);
printf("end address: %p \n", get_addr_range(func_name).end);

Где начальный адресдолжен быть фактическим адресом функции, как он выложен в данный момент в памяти.Я думаю, что gdb и objdump выполняют аналогичные действия, поэтому это должно быть возможно, верно?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 04 марта 2011

Вы можете посмотреть библиотеку BFD , поставляемую с binutils (с objdump и остальными).Я использовал его один раз вкратце, и, насколько я помню, это не совсем тривиально.

Есть несколько примеров использования (поиск «используя libbfd» или что-то в этом роде).Я бы порекомендовал также прочитать исходный код утилит binutils.

Есть также elfutils, который поставляется с подпрограммами ELF и DWARF.Хотя я этого не использовал, и документация выглядит скудно.

1 голос
/ 04 марта 2011

Возможно получить начальный адрес, но сложно получить конечный адрес для функции.GTK делает нечто похожее на то, что вы спрашиваете с динамическими привязками Glade.

Чтобы сделать это самостоятельно, вы скомпилируете свое приложение как динамически загружаемое изображение (например, совместно используемую библиотеку), используя libtool, и установите для изображения экспортированные имена, используя параметр libtool -export-dynamic.

Для получения дополнительной информации см. Эту ссылку на документацию Libtool.

Используемая команда ссылки:

libtool gcc -export-dynamic -o program main.o

После компиляцииесли требуется переключатель -export-dynamic, вы можете вызвать dlopen(), чтобы динамически открыть исполняемый образ в виде динамической библиотеки, и dlsym(), чтобы получить адрес определенных символов.

1 голос
/ 04 марта 2011

Обычно невозможно получить весь диапазон функций.

В лучшем случае вы можете получить начальный адрес. Вот пример, он НЕ переносимый:

#include <stdio.h>
int main(int argc, char *argv[])
{
    printf("fputs = %p\n", (void *)fputs);
    return 0;
}

Причина, по которой это невозможно, заключается в том, что в общем случае единственная информация, которую компоновщик использует о каждом объекте, будь то функция или данные, это его адрес и его имя (и несколько бит других данных). Компоновщик просто не заботится о том, насколько он велик.

Теперь вы можете узнать, насколько велика функция, изучив данные отладки, если для данной функции имеются данные отладки. Существуют библиотеки, которые вы можете использовать для анализа данных, поскольку это может быть несколько сложным. Вот ссылка на некоторую информацию о DWARF, если вы используете этот формат:

Обратите внимание, что вы можете помещать данные отладки в любой формат, который вам нравится, когда вы компилируете программу, или полностью его исключать. STABS и DWARF распространены в Linux. Однако тот факт, что исполняемый файл или библиотека не удалены, не означает, что данные отладки есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...