Изучение разделяемых библиотек (so)

Для того что бы выяснить какие функции экспортирует закрытая разделяемая библиотека (.so) и на основе этого написать свой C/C++ хидер (.h) воспользуемся двумя командами из пакета binutils. Поскольку формат ELF файлов не отличается для разных архитектур, то можно даже не устанавливать кросс утилиты.

Первая необходимая нам команда - readelf - позволяет получить самую разнообразную информацию о исполнимом файле или разделяемой библиотеки. Подробности можно узнать man elf, нас же на данном этапе интересует только таблица символических имён (symbols) библиотеки. Извлечь её можно дав команду

readelf -s -W libyourlibrary.so

Здесь ключ -s указывает, что нам нужна именно таблица имён (symbols), а ключ -W заставляет не обрезать выводимые данные под ширину терминала.

Таблицу с именами мы получаем в следующем виде:

   Num:    Value  Size Type    Bind   Vis      Ndx Name

    42: 42c11768    24 FUNC    GLOBAL DEFAULT   10 _ZNK10CAM_Engine15isCameraRunningEv
    43: 00000000   152 FUNC    GLOBAL DEFAULT  UND _ZN5QFileD1Ev

Имена у которых поле ‘Value’ равно нулю или поле ‘Ndx’ равно UND являются внешними по отношению к библиотеке, т.е. используются функциями библиотеки, но должны импортироватся из других библиотек. Их нам тоже необходимо будет отсечь.

Само имя функции переменной и т.п. содержится в последнем столбце. Имена используемые чистым C записываются как есть. Поскольку в C++ существуют пространства имён, классы, перегрузка функции из имени в таблицы мы можем извлечь много полезной информации. В частности это список параметров.

Имена кодируются специальным образом (mangling) и имеют малочитаемый вид. Что бы расшифровать имя, воспользуемся командой c++filt.

Что бы отсечь имена не экспортируемые библиотекой, отфильтруем вывод readelf с помощью скрипта awk. В итоге мы получаем цепочку команд:

readelf -s -W libezxcameraengine.so | awk '{ if($2) print $8 "\t\t // " $4 }' | c++filt | sort

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

К сожалению, не существует простого способа узнать тип возвращаемого значения. Тут поможет анализ бинарного кода, но в большинстве случаев нужный тип можно угадать ;-)

И наконец для имён функций в формате чистого C необходимые параметры можно узнать только анализом бинарного кода.


Для обзора экспортируемых и используемых функций воспользуемся командой:

readelf -s -W libezxbluetooth.so | c++filt | sort -k 8

Список так же будет отсортирован по именам функций/переменных.

И наконец команда:

objdump -dR libezxbluetooth.so | c++filt 

дизассемблирует бинарный код. Это конечно если у вас в системе установлен мультиархитектурный objdump. Иначе воспользуйтесь дампером из тулкита /arm-eabi/bin/arm-linux-gnueabi-objdump

 
comments powered by Disqus