Lldbを使用してAndroidネイティブアプリをAndroid Studioのネイティブデバッグからデバッグしようとしています。
私のネイティブアプリには、Android Studioと私がコンパイルした別の外部libother.soによってコンパイルおよび実行されるlibmain.soが1つ含まれています。デバッグ時に、ブレークポイントを設定できます。 libmain.soですが、libother.soではありません。
両方の共有オブジェクトが削除されますが、どういうわけかAndroid Studioはlldbに削除されていないバージョンのlibmain.soを通知します。libother.soについても同じことをしたいと思います。
ローカルマシン上のストリップされていないファイルからシンボルをロードするために、lldbにどのコマンドを与える必要がありますか?image list
を実行すると、メインの.soと、そのローカルのストリップされていないバージョンを指すパスが表示されます。
/Users/username/Projects/gow/Android/AppName/app/build/intermediates/binaries/debug/arm7/obj/armeabi-v7a/libmain.so
/var/folders/3w/5nr95lxx3qvdm2ylb8c8b7500000gn/T/./lldb/module_cache/remote-Android/.cache/B5F32653-0000-0000-0000-000000000000/libother.so
のようなパスを持つ2番目の.so
Lldbにlibother.so
のストリップされていないバージョンを見つけさせるにはどうすればよいですか?image add
とtarget symbols add
を試しましたが、機能しませんでした。
このスレッドの回答はMacOSXに固有のようです。私はLinuxを使用しているので、これらの回答はあまり役に立ちませんでした。しばらくして私はそれを理解しました、そしてここに非常に簡単な解決策があります。 「プロセスアタッチ」を実行する前に、次のコマンドを実行する必要があります。
settings set target.exec-search-paths /path/to/directory/with/unstripped/library/on/Host
この設定では、lldbはライブラリの正しいバージョンを見つけるのに問題はありません。
ところで、最新バージョンのAndroid Studioは、外部ライブラリに問題はありません(実際、同じ手法を使用して、「内部」と「外部」の両方のすべてのライブラリに正しいパスを設定します。少なくともGradleでビルドしている場合)。ただし、スタンドアロンのlldbを使用している場合、これは非常に便利です。
各デバッグセッションの開始後に入力しないようにするには、このコマンドをファイルに保存します(例:lldb.cmd
)次に、次のようにlldbを起動します。
./lldb -S lldb.cmd
「target.source-map」設定を使用します
(lldb)設定リストtarget.source-map
source-map-ビルド時のソースファイルと現在のシステム上のどこに存在するかの間の場所の変更を追跡するために使用されるソースパスの再マッピング。これは重複の配列で構成され、各重複の最初の要素は、ファイルがビルドされたときのファイルへのパスの一部(ルートから開始)であり、2番目の要素は元のビルド階層の残りの部分がルートになっている場所です。ローカルシステム。配列の各要素が順番にチェックされ、一致した最初の要素が優先されます。
つまり.
settings set target.source-map /build_src /source
ここで、建物環境は/build_src
の下にあり、.dSYMファイル(シンボル)は/source
の下にコピーされます。
編集:
多くの場合、バイナリはビルドされてリリースにパッケージ化された後に削除されます。ビルドシステムがストリップされていない実行可能ファイルを保存する場合、この実行可能ファイルへのパスは、キーDBGSymbolRichExecutableを使用して提供できます。
UUID値が与えられ、バイナリの場所を指定する特定のキーを持つplistを返すことが期待されるShellコマンドを作成できます。
次を使用してシェルスクリプトを有効にできます。
% defaults write com.Apple.DebugSymbols DBGShellCommands /path/to/shellscript
シェルスクリプトは、「23516BE4-29BE-350C-91C9-F36E7999F0F1」のようなUUID文字列値で呼び出されます。シェルスクリプトは、次の形式のplistで応答できます。
<?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>
詳細については、以下を参照してください。
http://lldb.llvm.org/symbols.html
https://www.mail-archive.com/[email protected]/msg01142.html
編集2:
実行可能ファイルのビルドUUIDを出力するターミナルコマンド
$ xcrun dwarfdump --uuid <PATH_TO_APP_EXECUTABLE>
完全を期すために、私がやったことは
-libmain.soのAndroid.mkの-Wl,--build-id=sha1
にLOCAL_LDFLAGS
を追加します
-/Users/username/Projects/gow/Android/AppName/app/build/intermediates/binaries/debug/arm7/obj/armeabi-v7a/
からストリップされていない共有オブジェクトにシンボリックリンクを追加します。
これにより、Android-StudioのLLDBは、削除されていない.soを見つけ、そのシンボルを正しく表示し、libmain.soコードにブレークポイントを追加できるようになりました。
この問題は、共有ライブラリに.note.gnu.build-id
セクションが含まれていない場合に発生することがわかりました。このセクションには、ファイルの一意のIDが含まれています。このセクションを作成するには、--build-id
スイッチをLDリンカーに渡す必要があります。
共有ライブラリにbuild-idを追加した後、LLDBは削除されていないバージョンのライブラリの使用を開始し、デバッグ情報を正常にロードしました。