私物

日記を私物化して、デバッグ風景の続き。
さて前回の復習から

    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のページング済み領域にセットされるので物理ページを割り当てる必要は一切ありません。(カーネルスタックをオンデマンドページングでやる勇気はありません。。。)
おそらくユーザースレッド作成の関数をそのままコピーしてしまったのでしょう。


ということでこの行をコメントアウトすればフックも完成のはずだ。


こういう動くけど実はバグだという種類のバグの特定は非常に難しい。
小説で言うならば誤植だけど、意味が通じてしまっていて著者の意図と違う意味として文章が解釈されてしまうようなものだ。