私物
日記を私物化して、デバッグ風景の続き。
さて前回の復習から
laddress=0x00101FD4 paddress=0x00801FD4 laddress=0x00101FD4 paddress=0x00101FD4
本来はladdress=paddressとなるべきページマッピングがおかしいのだ!!
さてここでMona的裏事情を明かすとリニアアドレス4GB空間の上位0-8MBは全てのプロセスに共通でリニアアドレス=物理アドレスとなっている。
どうしてそんなことになっているかって?
それは大人の事情だ!!(どうしても知りたい人はxxしてください。)
さて、上記アドレスの下位16bitはオフセットなので気にしないとしてpaddressが丁度8MBになっているのが非常に怪しい。これは某カーネルプログラマーがしこんだバグの予感がするぞヽ(`Д´)ノ
更に裏事情を明かすと8MBより大きい物理アドレスは物理ページプールに使われているのでページプールから物理アドレスを割り当てるところが怪しいのだ。
PageManager.cppのint PageManager::allocatePhysicalPage(PageEntry* pageEntry, bool present, bool writable, bool isUser)これだ。
こいつを追っていくとIDLEスレッド生成時になんだかおかしくなっているようだ。
ん・・・
ん・・・
001 void ThreadOperation::archCreateThread(Thread* thread, dword programCounter 002 , PageEntry* pageDirectory, LinearAddress stack) 003 { 004 ProcessOperation::pageManager->allocatePhysicalPage(pageDirectory, stack - Process::STACK_SIZE, true, true, true); // ★★これは・・・ 005 006 ThreadInfo* info = thread->tinfo; 007 ArchThreadInfo* ainfo = info->archinfo; 008 ainfo->cs = KERNEL_CS; 009 ainfo->ds = KERNEL_DS; 010 ainfo->es = KERNEL_DS; 011 ainfo->ss = KERNEL_SS; 012
はい。。。わかりました。この関数はカーネルスレッドを作成する関数ですが、スタックに物理アドレスを割り当てていますね。
これはまちがいです。Monaの全プロセスのカーネルタックは全部0-8MBのページング済み領域にセットされるので物理ページを割り当てる必要は一切ありません。(カーネルスタックをオンデマンドページングでやる勇気はありません。。。)
おそらくユーザースレッド作成の関数をそのままコピーしてしまったのでしょう。
ということでこの行をコメントアウトすればフックも完成のはずだ。
こういう動くけど実はバグだという種類のバグの特定は非常に難しい。
小説で言うならば誤植だけど、意味が通じてしまっていて著者の意図と違う意味として文章が解釈されてしまうようなものだ。