Android 1.6 エミュレーターでシンボルのないプログラムをデバッグしています。SO ライブラリのロード中にクラッシュ (シグナル) が発生しました。追跡しようとしています。クラッシュは、ライブラリの起動コードのどこかにあります。それはよくわかっています。制御がローダーから SO に移る前に、SO ローダー コード内の安全な場所を知っています。そこにブレークポイントを設定し、BLX からライブラリに至るまでステップを踏むことができます。ローダーのコードは Thumb です。ライブラリの起動コードは ARM です。
シンボルがないのでset arm force-mode xxx
、GDB に知らせるために使用します。ローダーでの停止につながるシーケンスを開始する前に、モードを Thumb に設定します。
ただし、問題は、BLX
命令に到達してシングルステップ ( si
) を実行しようとすると、デバッガが次の命令で停止せず、シグナルまで進んでしまうことです。BLXで実行するset arm force-mode arm
前に実行しsi
ても問題ないようです。
ライブラリの起動コードにブレークポイントを設定しても役に立ちません。GDB がブレークポイントを設定する正確な方法はわかりませんが、現在実行中のコードのモードと意図したブレークポイントのターゲット モードとの不一致が障害になっているようです。
編集:実行中のコードにモンキー パッチを適用して、適切な場所に BKPT コマンドを配置しようとしましたが、GDB はまだ壊れません。
EDIT2: コード セクションにモンキー パッチを適用しても機能しないようです。ただし、データ セクションの一部をスクラッチ領域として使用できます。それでも、BKPT によって GDB が壊れることはありません...
EDIT3: 3 行のコード スニペットにスクラッチ データ領域を使用すると、Thumb から切り替えてシグナルで GDB に戻ることができます。ただし、ARMモードになったので、GDBは何らかの理由でブレークポイントを設定できません。
BLX into library コマンドは次のようになりますblx r2
。r2 の値は 0x80601b60 です。これはライブラリの起動ルーチンです。
BLX で停止した場合は、次のようにします。データ セクションにスクラッチ領域があります。そこに次の ARM コマンドを配置します。
mov r12, 0 ; the value of r12 will be soon ruined by the code anyway
ldr r12, [r12] ; Provoke a SIGSEGV to stop GDB in ARM mode
mov pc, r2 ; To resume back into the library
次に、強制的に r2 の値をスクラッチ領域に設定し、GDB モードを ARM に設定して続行します。スクラッチ領域の SIGSEGV は自然にスローされます。
ここでは、ARM モード (CPU と GDB の両方の強制モード) にいます。ライブラリのエントリ ポイントである 0x80601b60 にブレークポイントを設定しました。r2 の値を 0x80601b60 に戻して、3 番目のコマンドがそこにジャンプするようにします。r12 の値を有効な読み取りアドレスに変更して、再試行時にシグナルが再スローされないようにします。そしてsignal 0
、信号なしで続行するようにコマンドを発行します。
コントロールが 0x80601b60 に移動し、ブレークポイントがヒットすることを期待しています。そうではありません。なぜだめですか?mov
ひょっとして pc に代入するときのセマンティクスが違うのでしょうか (is のようにldr rx, [pc]
)?
にブレークポイントを設定してもmov pc, r2
機能しません。シグナルモードで停止中に GDB にブレークポイントを設定すると問題がありますか? ただし、シグナルの前にブレークポイントを設定しても (Thumb モードで) 動作しません。
mov pc, r2
まだ見知らぬ人ですが、まったく実行されていないかのように制御が通過するケースに遭遇しています。しかし、 r12 を修正すると、前の命令が実行されます。
にシングルステップのアナログはありsignal 0
ますか?