Assemblyで作成したプログラムを実行すると、Illegal instruction
エラー。私が実行しているマシンにはデバッガや開発システムがないため、デバッグせずに、どの命令がエラーを引き起こしているのかを知る方法はありますか?つまり、あるマシンでコンパイルし、別のマシンで実行します。 SSE4.2をサポートしていないため、コンパイルしているマシンでプログラムをテストできません。それでも、プログラムを実行しているマシンはSSE4.2命令をサポートしています。
おそらく、アセンブラー(YASM)にSSE4.2命令を認識するように指示する必要があるのではないかと思います。gccに-msse4.2
国旗。それとも理由ではないと思いますか? YASMにSSE4.2命令を認識するように指示する方法はありますか?
[〜#〜] sigill [〜#〜] シグナルをトラップしてから、SA_SIGINFOをデコードして、プログラムがどのような不正な操作を行っているかを確認する必要があります。
実際には、プログラムに不正なオペコードが含まれているためではなく、プレーンデータまたはコードではなくランダムなアドレスにプログラムをジャンプさせるプログラム(バッファオーバーフローなど)があるため、不正な命令エラーが発生することがよくありますオペコードの開始。
最近、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専用の命令です を確認しました。
そのシステムでコアダンプを有効にできる場合は、プログラムを実行してクラッシュさせ、ターゲットマシンから開発マシンにコアダンプを引き出して、ターゲットアーキテクチャをデバッグするためにビルドされたGDBにロードします。クラッシュが発生した場所。 GDBのcore
コマンドを使用して、コアファイルをデバッガーにロードするだけです。
ターゲットでコアダンプを有効にするには:
ulimit -c unlimited
コアファイルの命名方法を制御する擬似ファイル(これらを使用して現在の構成を確認し、書き込みを行って構成を変更します):
/proc/sys/kernel/core_pattern
/proc/sys/kernel/core_uses_pid
私のシステムでは、コアダンプが有効になると、クラッシュするプログラムが作業ディレクトリに単に「core」という名前のファイルを書き込みます。おそらく目的には十分ですが、コアダンプファイルの名前を変更すると、必要に応じてコアダンプの履歴を保持できます(より断続的な問題のため)。
まあ...もちろん、トレース印刷を挿入できるので、コードの大部分をすばやく除外できます。それが終わったら、例えば.
$ objdump --disassemble my-crashing-program | less
次にジャンプします知っている関数がエラーの原因であるため、コードを読んで、奇妙に見えるものを探します。
objdump
が違法な指示をどのように表示するかは完全にはわかりませんが、目立つはずです。
手書きのアセンブリの場合、スタック管理の問題が原因でどこにも戻りません。すべてのレジスタを保存するデバッグ印刷ルーチンを作成し、すべての関数の先頭にその呼び出しを挿入します。
その後、あなたはあなたがどこまで行くかを見るでしょう...
(BTW、優れたエディター、およびアセンブラーのマクロ構文の十分な理解は、マシンコードを記述する際の命の恩人です。)
関数の最後にreturn
ステートメントがないと、これが発生する可能性があります。