2016-08-16 9 views
8

OSを書き込もうとすると、タスク切り替えのために現在の関数の終了アドレス(エピローグの直前)を取得する必要があります。
具体的には、私の問題は、コピーされたスタック内に新しく作成されたタスク(プロセス)に割り当てるEIPを取得することです。私は既にプロセスのレジスタを保存/復元することができましたが、子プロセスがEIPにどのような価値があるのか​​を知る必要があります。 GCC - ラベルアドレスは実際のラベルアドレスではなく現行のEIPを返します

私はC標準にGCCの拡張を使用: Labels as ValuesLocal Labels
をドキュメントから: あなたは単項演算子「& &」で現在の関数で定義されたラベルのアドレス(または含む関数)を取得することができます。値の型はvoid *です。
および: GCCでは、ネストされたブロックスコープ内のローカルラベルを宣言できます。ローカルラベルは通常のラベルと同じですが、宣言されているブロック内でのみ参照することができます(gotoステートメントで、またはそのアドレスを取ることによって)。

pid_t fork(void) 
{ 
    __label__ fork_end; 
    ... 
    task->regs.eip = (uintptr_t)&&fork_end; 
    ... 
    return task->pid; 
    fork_end:; 
} 

GCCは、非標準のコードについてだけ警告して、それをコンパイルしません。解体時に
はしかし、GDBは示しています

task->regs.eip = (uintptr_t)&&fork_end; 
0x00105008 <+87>: mov $0x105008,%edx 
0x0010500d <+92>: mov -0xc(%ebp),%eax 
0x00105010 <+95>: mov %edx,0x40(%eax) 
... 
    fork_end:; 
    } 
0x00105096 <+229>: leave 
0x00105097 <+230>: ret 

私はtask->regs.eip = (uintptr_t)&&fork_endl0x00105096ではなく0x00105008を救うことを期待しています。
CFLAGS-O0 -std=gnu99 -fgnu89-inline -DDEBUG -ggdb3 -ffreestanding -fbuiltinです(警告関連のオプションはここには表示されません)。

コメント__label__ fork_end;は何も変更されません。

+1

'&&'についてのgccのドキュメントへの参照を提供してください。拡張機能を使用するときは警告しません。 [ask]を参照し、必要な情報をすべて入力してください。 – Olaf

+0

編集され、@Olaf、gccは '-Wpedantic'オプションで非標準コードについて警告します。あなたのアドバイスをありがとう。 – Aerath

+0

ああ、そうです。拡張子付きの '-Wpedantic'を使うのは悪い考えです。とにかく、あなたのキャストは実装定義であり、 'uint32_t'はポインタを保持するためには求められず、1:1割り当てもありません。 64ビットシステムでは、すでに破棄されています。少なくとも、正しいタイプを使用してください。ポインタとして 'void * 'を使わず、整数を使う理由は何ですか? – Olaf

答えて

1

コンパイラはコードパスがそれにつながることはないので、ラベルを完全に最適化しているようです。私はreturnステートメントの前にラベルを移動し、割り当てとラベルの中間に実際のコードがあることを確認して、あなたが望む動作であると信じていることを確認しました。ここで私はテストにまとめたコードは次のとおりです。これに基づき

void *fork(void) { 
    __label__ fork_end; 
    void *test = &&fork_end; 

    test++; 

    fork_end: 
    return test; 
} 

、私はあなたが実際にラベルポイントがいずれかによって到達可能であることを保証するために、わずかに再ワーキングあなたのコードパスで欲しいものを得ることができることを期待しますコードパス。

+0

呼び出し元プロセスはこのラベルに到達する予定ではないので、GCCを騙して、それが到達可能でないとしてもそれを見えるようにするには、真実を使用しなければなりませんでした。 とにかくありがとうございます。@ joel-c – Aerath

関連する問題