LLDB: add symbols file?

2019-02-08 23:24发布

问题:

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.

回答1:

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



回答2:

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


回答3:

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.



回答4:

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.