私は、Ubuntu Linux 12.04、Intel x86_64 アーキテクチャ用のカスタム PE ハンドラーに取り組んできましたbinfmt
(これがおなじみの場合は、このプロジェクトに関連するいくつかの質問を既に投稿しています)。私が提供している情報の量が過剰である場合は、事前にお詫び申し上げます。
binfmt
ハンドラーはかなり標準的です。PE ヘッダーとセクションを読み込み、セクション テーブルで指定されたアドレスのユーザー空間メモリにそれらのセクションを書き込みます。そして、すべての準備が整ったら、私は電話します
start_thread(regs, entry_addr, current->mm->start_stack);
組み込みの Linux ハンドラとまったく同じです。私の場合、regs = 0xcf7dffb4
、entry_addr = 0x401000
、およびstart_stack = 0xbffff59b
。
Intel x86 アセンブリに次のコードがあります。
push ebp
mov ebp, esp
mov eax, 4
add eax, 5
pop ebp
ret
このプログラムをfasmで PE 形式の実行可能ファイル (math1.exe)にコンパイルbinfmt
し、insmod
. このプログラムを でデバッグするとgdb
、次のように表示されます。
(gdb) set disassembly-flavor intel
(gdb) x/6i 0x401000
0x401000: push ebp
0x401001: mov ebp,esp
0x401003: mov eax,0x4
0x401008: add eax,0x5
0x40100b: pop ebp
0x40100c: ret
コードが正しいアドレスにロードされていることがわかります。それで:
(gdb) run
Starting program: /media/sf_Sandbox/math1.exe
Program received signal SIGSEGV, Segmentation fault.
0x0040100c in ?? ()
レジスタ ダンプを実行すると、次のようになります。
(gdb) info registers
eax 0x9 9
ecx 0x81394e8 135501032
edx 0x8137808 135493640
ebx 0x8139548 135501128
esp 0xbfffe59b 0xbfffe59b
ebp 0x0 0x0
esi 0x81394e8 135501032
edi 0x2f7ff4 3112948
eip 0x40100c 0x40100c
...other registers...
コードが実行されたことがわかります。なぜならeax = 0x9
、そうあるべきだからです。ただし、表面的には、これがステートメントでセグメンテーション違反になる理由は見つかりませんret
。調べdmesg
て、見つけた
math1.exe[1864] general protection ip:40100c sp:bffff5bd error:0
しかし、これを引き起こしている可能性のあるものに関するドキュメントはほとんど見つかりませんでした。同じアセンブラで ELF 形式にコンパイルされた同じコードが問題なく実行されるため、問題はコード自体ではないことはわかっています。
この問題に関する私の現在の理論は次のとおりです。
- ハンドラーでスタック ポインターをいじることはあまりありません。組み込みの Linux ハンドラ (ELF、a.out、およびフラット形式の 3 つを挙げます) には、、、および引数を処理する関数があり
create_*_tables()
ます。テスト プログラムは入力を受け取らないため、最初はこの関数を含めませんでしたが、関数を (フラット ハンドラーから) 実装しても、これまでのところ問題は解決しません。(盲目的に貼り付けて他のモジュールから関数を呼び出すのは悪い考えであることはわかっていますが、その関数の a.out バージョンとフラット バージョンは本質的に同一であるため、実行形式にはあまり依存していないようです。試してみます。)argc
argv
envp
create_flat_tables()
- の実行前後に発生する一連の関数呼び出しに関するこの記事を見つけました
main()
。math1.exeのobjdump
には、上記のアセンブリ コードのみが含まれていますが、 ELF 形式へのアセンブリ (ファイルを生成する) およびリンク(ELF バイナリを取得する)objdump
後の同じプログラムの には、記事に記載されている他の関数が含まれています ( 、など)。おそらく、これらの機能は、私が以前考えていたよりも、Linux プラットフォームで必須です。*.o
gcc
_start()
__libc_start_main()
説明/提案/追加のトラブルシューティング手順を探しています。前もって感謝します!