Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lldb: how to call a function from a specific library/framework

Tags:

macos

gdb

lldb

Problem: In project we have localization functions which are specific to a framework/dynamic library. That is they have identical name but fetch resources from different bundles/folders

I'd want to call a function from a specific library, something similar to:

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)

but all these variants don't work.

Adding gdb in tags hoping the same semantic if exists will work on lldb as well.

like image 702
dev_null Avatar asked Dec 09 '22 10:12

dev_null


1 Answers

lldb's expression parser doesn't currently have the equivalent of gdb's foo.c::function meta-symbol to encode a function from a specific source file.

Please feel free to file a bug requesting this at bugreporter.apple.com. It will get duped to the one I filed a while ago, but dups are votes for features, and we haven't gotten around to this one yet 'cause nobody but me asked for it...

For the nonce, you will have to do this by hand. Here's a silly example for calling printf, which I happen to know is in libsystem_c.dylib on OS X. First, I find the address in the shared library I am interested in:

(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"

The first address (the one under Address) is the address of the function in the dylib, not where it got loaded in the running program. That's not immediately useful. I could calculate the library's load offset if I wanted to and apply it to the file address, but fortunately the first address in the Symbol's address range is the address in the running program so I don't have to. 0x00007fff91307948 is the address I want.

Now I want to call that address. I do this in two steps because it makes the casting easier, like:

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

Now I have a function I can call over and over:

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

If you are going to do this over and over, you can write a Python function that finds the symbol out of the library of interest, and constructs the expression that calls the right function. The Python API's include calls to get symbols from a particular module (lldb-speak for loadable binary images), get their addresses, evaluate expressions, etc.

like image 93
Jim Ingham Avatar answered Jan 03 '23 14:01

Jim Ingham