lldb: как вызвать функцию из определенной библиотеки / фреймворка

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

Я хотел бы вызвать функцию из определенной библиотеки, что-то похожее на:

lldb> p my_audio_engine.framework::GetL10nString( stringId );
lldb> expr --shlib my_audio_engine.framework -- GetL10nString();
lldb> p my_audio_engine`L10N_Utils::GetString(40000)

но все эти варианты не работают.

Добавление gdb в теги в надежде, что такая же семантика, если она существует, будет работать и на lldb.

1 ответ

Решение

В данный момент синтаксический анализатор выражений lldb не имеет эквивалента метасимвола gdb foo.c::function для кодирования функции из определенного исходного файла.

Пожалуйста, не стесняйтесь сообщать об ошибке, запрашивающей это на bugreporter.apple.com. Он будет дублирован на тот, который я подал некоторое время назад, но ошибки - это голос за функции, а мы еще не дошли до этого, потому что никто, кроме меня, не просил об этом...

Для одноразового использования вам придется сделать это вручную. Вот глупый пример вызова printf, который, как я случайно знаю, находится в libsystem_c.dylib на OS X. Сначала я нахожу адрес в разделяемой библиотеке, которая мне интересна:

(lldb) image lookup -vn printf libsystem_c.dylib
1 match found in /usr/lib/system/libsystem_c.dylib:
        Address: libsystem_c.dylib[0x0000000000042948] (libsystem_c.dylib.__TEXT.__text + 266856)
        Summary: libsystem_c.dylib`printf
         Module: file = "/usr/lib/system/libsystem_c.dylib", arch = "x86_64"
         Symbol: id = {0x00000653}, range = [0x00007fff91307948-0x00007fff91307a2c), name="printf"

Первый адрес (адрес под адресом) - это адрес функции в dylib, а не там, где она была загружена в работающей программе. Это не сразу полезно. Я мог бы рассчитать смещение загрузки библиотеки, если бы захотел, и применить его к адресу файла, но, к счастью, первый адрес в диапазоне адресов Symbol - это адрес в работающей программе, поэтому мне не нужно это делать. 0x00007fff91307948 - это адрес, который я хочу.

Теперь я хочу позвонить по этому адресу. Я делаю это в два этапа, потому что это облегчает кастинг, например:

(lldb) expr typedef int (*$printf_type)(const char *, ...)
(lldb) expr $printf_type $printf_function = ($printf_type) 0x00007fff91307948

Теперь у меня есть функция, которую я могу вызывать снова и снова:

(lldb) expr $printf_function("Hello world %d times.\n", 400)
Hello world 400 times.
(int) $2 = 23

Если вы собираетесь делать это снова и снова, вы можете написать функцию Python, которая находит символ из интересующей библиотеки и создает выражение, которое вызывает нужную функцию. API-интерфейсы Python включают в себя вызовы для получения символов из определенного модуля (lldb-говорить для загружаемых двоичных изображений), получения их адресов, оценки выражений и т. Д.

Другие вопросы по тегам