39

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

-msse4.2フラグを渡してgccで行うのと同じように、アセンブラ(YASM)にSSE4.2命令を認識するように指示する必要があるためだと思います。それともそれが理由ではないと思いますか?YASM に SSE4.2 命令を認識させる方法はありますか?

おそらく、 SIGILLシグナルをトラップしてから、SA_SIGINFO をデコードして、プログラムが行う不正な操作の種類を確認する必要があります。

4

6 に答える 6

46

最近、132 終了ステータス コード (128 + 4: シグナルによってプログラムが中断された + 不正な命令シグナル) によるクラッシュを経験しました。これが、クラッシュの原因となっている命令を特定する方法です。

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

$ ulimit -c unlimited

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

$ 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 のみの命令であることを確認しました。

于 2016-10-24T17:01:00.183 に答える
34

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

于 2012-04-27T16:15:50.967 に答える
11

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

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

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

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

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

于 2012-04-27T18:08:25.143 に答える
4

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

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

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

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

于 2012-04-27T16:13:09.873 に答える
4

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

そうすれば、どこまで行けるかがわかります...

(ところで、優れたエディターとアセンブラーのマクロ構文の十分な理解は、マシン コードを作成する際の命の恩人です。)

于 2012-04-27T16:22:42.903 に答える