I'm trying to debug an android native app from Android Studio's native debugging using lldb.
My native app contains one libmain.so that is compiled and run by Android Studio and another external libother.so compiled by me. when debugging, I am able to set breakpoints in libmain.so but not libother.so.
Both shared objects are stripped but somehow Android Studio makes lldb know about the unstripped version of libmain.so. I want to do the same for libother.so.
What command do I need to give lldb so that it would load the symbols from an unstripped file on my local machine?
When I do image list
I see the main .so with a path the points to its local unstripped version:
/Users/username/Projects/gow/android/AppName/app/build/intermediates/binaries/debug/arm7/obj/armeabi-v7a/libmain.so
and the second .so with a path like
/var/folders/3w/5nr95lxx3qvdm2ylb8c8b7500000gn/T/./lldb/module_cache/remote-android/.cache/B5F32653-0000-0000-0000-000000000000/libother.so
How do I make lldb find the unstripped version of libother.so
?
I tried image add
and target symbols add
but it didn't work.
use the "target.source-map" setting
(lldb) settings list target.source-map
source-map -- Source path
remappings used to track the change of location between a source file
when built, and where it exists on the current system.
It consists of an array of duples, the first element of each duple is some part (starting at the root) of the path to the
file when it
was built, and the second is where the remainder of the original build hierarchy is rooted on the local system. Each
element of the
array is checked in order and the first one that results in a match wins.
i.e.
settings set target.source-map /build_src /source
where the building environment is under /build_src
and the.dSYM files (symbols) are copied under /source
EDIT:
Binaries are often stripped after being built and packaged into a release. If your build systems saves an unstripped executable a path to this executable can be provided using the key DBGSymbolRichExecutable
You can write a shell command that will be given a UUID value and is
expected to return a plist with certain keys that specify where the binary
is.
You can enable the shell script using:
% defaults write com.apple.DebugSymbols DBGShellCommands /path/to/shellscript
Your shell script will be invoked with a UUID string value like
"23516BE4-29BE-350C-91C9-F36E7999F0F1". The shell script can respond with a
plist in the following format:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
<plist version="1.0">
<dict>
<key>23516BE4-29BE-350C-91C9-F36E7999F0F1</key>
<dict>
<key>DBGArchitecture</key>
<string>i386</string>
<key>DBGBuildSourcePath</key>
<string>/path/to/build/sources</string>
<key>DBGSourcePath</key>
<string>/path/to/actual/sources</string>
<key>DBGDSYMPath</key>
<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
<key>DBGSymbolRichExecutable</key>
<string>/path/to/unstripped/exectuable</string>
</dict>
<key>A40597AA-5529-3337-8C09-D8A014EB1578</key>
<dict>
<key>DBGArchitecture</key>
<string>x86_64</string>
.....
</dict>
</dict>
</plist>
for more details please see:
http://lldb.llvm.org/symbols.html
https://www.mail-archive.com/lldb-dev@cs.uiuc.edu/msg01142.html
EDIT 2:
Terminal command to print an executable's build UUID
$ xcrun dwarfdump --uuid <PATH_TO_APP_EXECUTABLE>
source
The answers in this thread seem to be specific for MacOSX. I am using Linux, so these answers weren't very helpful. After some time I've figured it out, and here is a very simple solution. Before you do "process attach" you should execute the following command:
settings set target.exec-search-paths /path/to/directory/with/unstripped/library/on/host
With this setting lldb has no problems finding the correct version of the library.
BTW, latest versions of Android Studio don't have any problems with external libraries (in fact, the same technique is used to set correct paths all libraries, both "internal" and "external", at least if you're building with Gradle). But if you use standalone lldb, this can be very handy.
To avoid typing it after start of each debugging session you can save this command to file (e.g. lldb.cmd
) and then start lldb like this:
./lldb -S lldb.cmd
For completeness, what I ended up doing is
- add -Wl,--build-id=sha1
to the LOCAL_LDFLAGS
in the Android.mk of libmain.so
- add a symlink from /Users/username/Projects/gow/android/AppName/app/build/intermediates/binaries/debug/arm7/obj/armeabi-v7a/
to the unstripped shared object.
That allowed Android-Studio's LLDB to find the unstripped .so, correctly present its symbols and allowed me to add breakpoints in libmain.so code.
I've found that this issue occurs when a shared library does not contain the .note.gnu.build-id
section. This section contains an unique ID of the file. To create this section it is needed to pass the --build-id
switch to the LD linker.
After addition of the build-id to my shared library LLDB started to use un-stripped version of the library and successfully loaded its debug information.