web-dev-qa-db-ja.com

デバッグせずに、どのアセンブリ命令が不正な命令エラーを引き起こしたかを調べる

Assemblyで作成したプログラムを実行すると、Illegal instructionエラー。私が実行しているマシンにはデバッガや開発システムがないため、デバッグせずに、どの命令がエラーを引き起こしているのかを知る方法はありますか?つまり、あるマシンでコンパイルし、別のマシンで実行します。 SSE4.2をサポートしていないため、コンパイルしているマシンでプログラムをテストできません。それでも、プログラムを実行しているマシンはSSE4.2命令をサポートしています。

おそらく、アセンブラー(YASM)にSSE4.2命令を認識するように指示する必要があるのではないかと思います。gccに-msse4.2 国旗。それとも理由ではないと思いますか? YASMにSSE4.2命令を認識するように指示する方法はありますか?

[〜#〜] sigill [〜#〜] シグナルをトラップしてから、SA_SIGINFOをデコードして、プログラムがどのような不正な操作を行っているかを確認する必要があります。

27
pythonic

実際には、プログラムに不正なオペコードが含まれているためではなく、プレーンデータまたはコードではなくランダムなアドレスにプログラムをジャンプさせるプログラム(バッファオーバーフローなど)があるため、不正な命令エラーが発生することがよくありますオペコードの開始。

30
ouah

最近、132の終了ステータスコード(128 + 4:信号によって中断されたプログラム+不正な命令信号)が原因でクラッシュが発生しました。クラッシュの原因となった命令をどのように把握したかを以下に示します。

まず、コアダンプを有効にしました。

$ ulimit -c unlimited

興味深いことに、私がバイナリを実行していたフォルダには、coreという名前のフォルダが含まれていました。 LinuxにPIDをコアダンプに追加するように指示する必要がありました。

$ Sudo sysctl -w kernel.core_uses_pid=1

次に、プログラムを実行し、core.23650という名前のコアを取得しました。バイナリとコアをgdbでロードしました。

$ gdb program core.23650

Gdbに入ると、次の情報が表示されました。

Program terminated with signal SIGILL, Illegal instruction.
#0  0x00007f58e9efd019 in ?? ()

つまり、0x00007f58e9efd019アドレスメモリでの不正な命令が原因でプログラムがクラッシュしました。次に、asmレイアウトに切り替えて、最後に実行された命令を確認しました:

(gdb) layout asm
>|0x7f58e9efd019  vpmaskmovd (%r8),%ymm15,%ymm0
 |0x7f58e9efd01e  vpmaskmovd %ymm0,%ymm15,(%rdi)
 |0x7f58e9efd023  add    $0x4,%rdi
 |0x7f58e9efd027  add    $0x0,%rdi

エラーの原因は命令vpmaskmovdでした。どうやら、AVX2命令セットをサポートしていないシステムで、AVX2アーキテクチャ向けのプログラムを実行しようとしていたようです。

$ cat /proc/cpuinfo | grep avx2

最後に、 vpmaskmovdはAVX2専用の命令です を確認しました。

25
Diego Pino

そのシステムでコアダンプを有効にできる場合は、プログラムを実行してクラッシュさせ、ターゲットマシンから開発マシンにコアダンプを引き出して、ターゲットアーキテクチャをデバッグするためにビルドされたGDBにロードします。クラッシュが発生した場所。 GDBのcoreコマンドを使用して、コアファイルをデバッガーにロードするだけです。

  • ターゲットでコアダンプを有効にするには:

    ulimit -c unlimited
    
  • コアファイルの命名方法を制御する擬似ファイル(これらを使用して現在の構成を確認し、書き込みを行って構成を変更します):

    /proc/sys/kernel/core_pattern
    /proc/sys/kernel/core_uses_pid
    

私のシステムでは、コアダンプが有効になると、クラッシュするプログラムが作業ディレクトリに単に「core」という名前のファイルを書き込みます。おそらく目的には十分ですが、コアダンプファイルの名前を変更すると、必要に応じてコアダンプの履歴を保持できます(より断続的な問題のため)。

11
Michael Burr

まあ...もちろん、トレース印刷を挿入できるので、コードの大部分をすばやく除外できます。それが終わったら、例えば.

$ objdump --disassemble my-crashing-program | less

次にジャンプします知っている関数がエラーの原因であるため、コードを読んで、奇妙に見えるものを探します。

objdumpが違法な指示をどのように表示するかは完全にはわかりませんが、目立つはずです。

4
unwind

手書きのアセンブリの場合、スタック管理の問題が原因でどこにも戻りません。すべてのレジスタを保存するデバッグ印刷ルーチンを作成し、すべての関数の先頭にその呼び出しを挿入します。

その後、あなたはあなたがどこまで行くかを見るでしょう...

(BTW、優れたエディター、およびアセンブラーのマクロ構文の十分な理解は、マシンコードを記述する際の命の恩人です。)

4
DigitalRoss

関数の最後にreturnステートメントがないと、これが発生する可能性があります。

2
Gabriel