ReactOS開発の手引き

by 片山博文MZ

2020年4月21日

概要

Windows互換OS、ReactOSの開発者になるための知識について解説する。

必須条件

準備1

現在利用できるフリーの仮想マシンには、 QemuVirtualBoxVMWare があります。

準備2 (Visual Studioを使わない場合)

準備2 (Visual Studioを使う場合)

2019.07.26 少し修正しました。

※2018.12.20 PATH設定とconfigureのコマンドラインを少し修正しました。日本語Visual Studioでもビルドできるはず。できないときは連絡してね。

※RosBEのCMakeは少しハックされたCMakeです。オリジナルのCMakeとはちょっと違います。興味がある人は、https://github.com/reactos/RosBEをご覧下さい。

Win2003評価版のデバッグ方法

Win2003のデバッグの練習

では、実際にデバッグを試してみよう。今回は、explorer.exeSHELL32!SHFileOperationWをデバッグする。

1. 「ファイル」メニューから「Attach to Kernel」を選択し、「OK」をクリックする。
2. デバッガが再接続待ちになる。デバッグを開始するためにWin2003を起動する。
3. 「Break」ボタンを押してブレークする。これでデバッガコマンドが入力できる状態になる。
4. デバッガで「!process 0 0」コマンドを実行。プロセスのリストが表示される。そのリストの中からexplorer.exeを探す。

...
PROCESS 81dec8b0  SessionId: 0  Cid: 06f4    Peb: 7ffdf000  ParentCid: 06d0
    DirBase: 14d28000  ObjectTable: e1937640  HandleCount: 350.
    Image: explorer.exe
...

5. 「explorer.exe」という項目に「PROCESS 81dec8b0」と書いてあるから、これを使ってexplorer.exeのプロセスを アタッチする。「.process 81dec8b0」コマンドを実行。さらに「.reload /user」コマンドを実行してユーザモードのデバッグを可能にする。
6.「LM」コマンドを実行して、モジュールのリストを表示する。

kd> LM

...
7c800000 7c8c2000   ntdll      (pdb symbols)          C:\symbols\ntdll.pdb\4613B105DA224E789F26051F952BE5A82\ntdll.pdb
7c8d0000 7d0cf000   SHELL32    (deferred)
7d1e0000 7d27c000   ADVAPI32   (deferred)
...

7. モジュールにSHELL32があるのが分かる。さらにシンボルを検索するために「x SHELL32!SHFile*」を実行する。

kd> x SHELL32!SHFile*

7c9a1cde          SHELL32!SHFileOperationW (_SHFileOperationW@4)
7c9a1fc6          SHELL32!SHFileOperationA (_SHFileOperationA@4)
7c959535          SHELL32!SHFileSysBindToStorage (_SHFileSysBindToStorage@24)

8. ここでシンボル「SHELL32!SHFileOperationW」にデバッグブレークを設定するために「bp SHELL32!SHFileOperationW」を実行する。
9. 「g」コマンドでWin2003のデバッグ実行を再開する。
10. Win2003を操作して、ファイルをコピーして貼り付けしようとすると、ブレークが発生する。

kd> g
Breakpoint 0 hit
SHELL32!SHFileOperationW:
001b:7c9a1cde 8bff            mov     edi,edi

11. 「kp」コマンドを実行すると呼び出し履歴が得られる。

kd> kp
 # ChildEBP RetAddr  
00 01aef86c 7ca05f85 SHELL32!SHFileOperationW
01 01aefce0 7ca062a3 SHELL32!CFSDropTarget::_MoveCopy+0x1ff
02 01aeff38 7ca06349 SHELL32!CFSDropTarget::_DoDrop+0x270
03 01aeff54 77da3f12 SHELL32!CFSDropTarget::_DoDropThreadProc+0x46
04 01aeffb8 77e6482f SHLWAPI!WrapperThreadProc+0x94
05 01aeffec 00000000 kernel32!BaseThreadStart+0x34

これはSHFileOperationW関数がCFSDropTarget::_MoveCopy 関数から呼び出されているのが分かる。
12. ステップ実行すれば、SHELL32!SHFileOperationWのデバッグが可能になる。

ReactOSのデバッグ方法

おおざっぱに言うと、デバッグ方法は次のようになる。

1. VirtualBoxにReactOSにインストールした後、電源OFFの状態でVirtualBoxの「設定」でシリアルポートを有効化し、適当な場所のRawファイルに出力するようにする。

2. ReactOSを起動し、起動メニューで「ReactOS (Debug)」を選ぶ。

3. するとデバッグモードで起動し、Rawファイルにデバッグ情報が出力される。

ReactOSでは、ソースコードの中でDPRINT1文(もしくはERR文)をprintfのように使えばデバッグ出力されるようになっている。

キーボードのTab+Kを押せば、デバッガに強制的に移行する。 デバッガに入ると、VirtualBoxの画面の動きが止まるが、 気にせず、Rawファイルを監視しながら、画面をアクティブにした状態でキーボードでデバッガに入力できる。

こちらも参照:Debugging - ReactOS Wiki

ReactOSのデバッグの練習

今回は、「explorer.exe」プロセスの中の「kernel32.dll」にある CreateDirectoryWkernel32!CreateDirectoryW)をデバッグする。

1. CreateDirectoryWのアドレスが欲しいので "dll/win32/kernel32/client/file/dir.c"CreateDirectoryWの関数の中に次の行を追加してリビルドする。

   DPRINT1("CreateDirectoryW address: %p\n", CreateDirectoryW);

2. ReactOSにGuest Additionsをインストールした後、デバッグモードで起動する。
3. デスクトップにフォルダを作成すると「CreateDirectoryW address: ...」のような行がデバッグ出力されるはずだ。

(dll/win32/kernel32/client/file/dir.c:102) CreateDirectoryW address: 7C5DA9D0
CreateDirectoryWのアドレスは0x7c5da9d0だとわかる。これを使って後でブレークポイントを設定する。

4. Tab+K でデバッガに入る。


Entered debugger on embedded INT3 at 0x0008:0x80958ae8.

5. 「proc list」でプロセスの一覧を得る。

kdb:> proc list
  PID         State       Filename
  0x00000004  In Memory   System
  0x00000068  In Memory   smss.exe
  0x00000098  In Memory   csrss.exe
  0x000000ac  In Memory   winlogon.exe
  0x000000c4  In Memory   services.exe
...
  0x000001d8  In Memory   explorer.exe
...

6. 一覧の中から「explorer.exe」を探すと

  0x000001d8  In Memory   explorer.exe

という行が見つかるので、「explorer.exe」プロセスにアタッチするために「proc attach 0x1d8」を実行する。

kdb:> proc attach 0x1d8
Attached to process 0x000001d8, thread 0x000001db.

7. CreateDirectoryWのアドレスは0x7c5da9d0だった。 これを使ってブレークポイントを設定する。

kdb:> bpx 0x7c5da9d0
Breakpoint 0 inserted.
Breakpoint 0 enabled.
kdb:> set condition INT3 first always

8. 「cont」コマンドで実行を再開し、再びフォルダを作ってみる。ブレークポイントで停止する。

kdb:> cont

Entered debugger on breakpoint #0: EXEC 0x001b:0x7c5da9d0
kdb:>

9. 「bt」コマンドで呼び出し履歴を取得してみる。

kdb:> bt
Eip:
<kernel32.dll:2a9d0>
Frames:
<shell32.dll:55876>
<shell32.dll:55db3>
<shell32.dll:570a7>
<shell32.dll:48654>
<shell32.dll:4985e>
<shell32.dll:49f70>
<shell32.dll:29af8>
<shell32.dll:70d9b>
<shell32.dll:71e40>
<shell32.dll:71edc>
<shell32.dll:6a456>
<shell32.dll:6a9cf>
...

ここで「kernel32.dll:2a9d0」やら「shell32.dll:55876」など、わけのわからないものが 書かれているが、これらは、RosBEの「raddr2line」というコマンドラインツールを使えば、 ソースコードの行番号として解読できる。

解読した結果は次の通り。

<kernel32.dll:2a9d0>: dll/win32/kernel32/client/file/dir.c:92 (CreateDirectoryW)
<shell32.dll:55876>: dll/win32/shell32/shlfileop.cpp:1310 (copy_dir_to_dir)
<shell32.dll:55db3>: dll/win32/shell32/shlfileop.cpp:1502 (copy_files)
<shell32.dll:570a7>: dll/win32/shell32/shlfileop.cpp:1966 (SHFileOperationW)
<shell32.dll:48654>: dll/win32/shell32/droptargets/CFSDropTarget.cpp:90 (CFSDropTarget::_CopyItems)
<shell32.dll:4985e>: dll/win32/shell32/droptargets/CFSDropTarget.cpp:647 (CFSDropTarget::_DoDrop)
<shell32.dll:49f70>: dll/win32/shell32/droptargets/CFSDropTarget.cpp:442 (CFSDropTarget::Drop)
<shell32.dll:29af8>: dll/win32/shell32/CShellLink.cpp:3167 (CShellLink::Drop)
<shell32.dll:70d9b>: dll/win32/shell32/CSendToMenu.cpp:91 (CSendToMenu::DoDrop)
<shell32.dll:71e40>: dll/win32/shell32/CSendToMenu.cpp:439 (CSendToMenu::DoSendToItem)
<shell32.dll:71edc>: dll/win32/shell32/CSendToMenu.cpp:499 (CSendToMenu::InvokeCommand)
<shell32.dll:6a456>: dll/win32/shell32/CDefaultContextMenu.cpp:1020 (CDefaultContextMenu::InvokeShellExt)
<shell32.dll:6a9cf>: dll/win32/shell32/CDefaultContextMenu.cpp:1195 (CDefaultContextMenu::InvokeCommand)
<shell32.dll:5e0ee>: dll/win32/shell32/CDefView.cpp:1391 (CDefView::InvokeContextMenuCommand)
<shell32.dll:5e61b>: dll/win32/shell32/CDefView.cpp:1539 (CDefView::OnContextMenu)
<shell32.dll:d1e84>: dll/win32/shell32/CDefView.cpp:321 (CDefView::ProcessWindowMessage)
<shell32.dll:d1a3e>: sdk/lib/atl/atlwin.h:1565 (CDefView::WindowProc)

開発を始める

結び

ReactOSの開発について解説した。

分からないことがあれば、 katayama.hirofumi.mz@gmail.com にご連絡を。

inserted by FC2 system