3

Android でネイティブ ライブラリの読み込みイベントにブレークポイントを設定するにはどうすればよいですか?

dlopen()にブレークポイントを設定することは良い出発点になると思いますが、 libc.so/system/bin/linkerのシンボルがロードされている場合でも、gdb は dlopen 関数を見つけることができません。

nmツールもdlopen()の場所を報告しないため、Androidは.soファイルの特別な形式を使用しているようです。

ブレークポイントを手動で設定できるように、名前で関数アドレスを見つけるのに役立つ問題または Android 固有の .so ダンプ ツールの回避策はありますか?

編集:

私がやろうとしているのは、任意のネイティブ ライブラリがロードされたとき、つまりコード (ライブラリ内でさえない) がdlopen()関数を呼び出したときにトリガーされるブレークポイントを設定することです。

問題は、Android GDB が保留中のブレークポイントをサポートしていないことです。私のシナリオは次のようなものです:

  1. アプリを起動して停止します。
  2. アプリが再開され、ネイティブ ライブラリが読み込まれます。
  3. 私の関数はライブラリから呼び出されます (アプリがロードされたときに 1 回だけ)。

#1の後にブレークポイントを設定すると、ライブラリがまだ存在せず、android-gdbが再バインドできないため機能しません。プログラムを実行させてから、もう一度停止してブレークポイントを設定すると、すでに #3 を過ぎているため、ブレークポイントは役に立たなくなります。

#1 でブレークポイントをdlopen()に設定して回避しようとしています。次に、ライブラリにヒットしてロードすると (つまり #2)、実際のブレークポイントを設定します。

通常の ARM nm と objdump を使用しても効果はありません。libc.so を NM'ing すると、dlopen()が未定義であることがわかります。

00016188 T dlmemalign
         U dlopen
00016338 T dlpvalloc

/ system/bin/linkerバイナリには物理的にdlopenテキスト ( .rodataセクションの最初のバイト) が含まれていますが、nmには次のテキストが表示されます。

arm-linux-androideabi-nm.exe: linker: No symbols

objdump で逆アセンブルすると、シンボル名が得られません。

Android ソースを探し回ると、次のソース ファイルが明らかになりました。

http://dexandroid.googlecode.com/svn/trunk/bionic/linker/dlfcn.c

dlopen() は /system/bin/linker 内で実際に定義されているように見えますが、非標準のシンボル解決メカニズムを使用しています (少なくとも、最初のコメントに基づいて):

/* This file hijacks the symbols stubbed out in libdl.so. */

質問に戻ると、ライブラリがロードされたときに実際のブレークポイントを設定するために、どうすればdlopen()にブレークポイントを設定できますか?

4

1 に答える 1

3

通常、任意のアーム objdump が機能するはずですが、ndk ディレクトリに 1 つ存在します。腕のないリーデルフでも機能する場合があります。

別のライブラリを開くためにそれを明示的に使用していない限り、ライブラリで dlopen() を見つけると予想する理由がわかりません-通常、libdvm.soから呼び出されると思うでしょう。 libdl.so (Android 用にビルドされたバージョンの grep を持つことは非常に便利です。lib ディレクトリで文字列を見つけることができますが、それらがインポートまたはエクスポートであるかどうかを確認したい場合は、おそらく adb pull および objdump のファイルが必要です)興味)。

ロード中のライブラリ ファイルにブレークポイントを設定しようとしている場合は、静的初期化関数 (C レベルまたはロード時の jni) の 1 つを実装し、そこにブレークポイントを配置してみてください。

編集:

arm の objdump は、共有ライブラリからインポートされたシンボルに使用される plt を介してリンケージをデコードしないことが判明しましたが、x86 などの他のプラットフォームではデコードされます。これにより、デバイスのシステム ライブラリから予想されるように、デバッグ シンボルが取り除かれたバイナリの意味を理解することが非常に難しくなる可能性があります。arm でこれを行うために、binutils ソースにパッチを当てることができました。最終的にはそれをどこかに提出したいと考えていますが、当面の間、パッチを適用したバージョンのソースはhttps://github.com/cstratton/binutils-android-decodepltで入手できます

objdump バイナリを prebuilt-linux-x86/ ディレクトリに置きましたが、それがどれほど移植性があるかはわかりません。

于 2012-06-24T23:55:34.593 に答える