Windows CEは、OSのソースコードが付いてくるのがいいところ。
と以前の日記で書いたが、もちろんすべてのソースコードがあるわけではない。ソースがないものも当然ある。例えば、Internet ExplorerはUI部分(つまり、WebBrowserコントロールのホスト部分)のソースコードはあるが、WebBrowserコントロールのソースコードはない。
しかしそれでもなお素晴らしいのは、mapファイルが提供されることだ。ソースコードがなくても、mapファイルがあることでモジュールの内部構造をある程度推定することができる。なぜならmapファイルにはモジュール内部のほぼすべてのシンボルの名前とアドレスが書いてあるからだ。
例えば、印刷を呼び出したときのスタックトレースはこんな感じになる。
(エミュレーター構成でOSを作成すれば、PC上でWindows CEのエミュレーターウィンドウが開いてOSをエミュレート実行できるし、OSをデバッグビルドすれば任意のタイミングでOSの実行そのものをブレークして、任意のOSスレッドのスタックトレースを見ることができる。)
shdocvw.dll!CDocHostUIHandler::DoTemplatePrinting()
shdocvw.dll!CDocHostUIHandler::Exec()
mshtml.dll!CDoc::PrintHandler()
mshtml.dll!CDoc::ExecHelper()
mshtml.dll!CDoc::Exec()
shdocvw.dll!CDocObjectHost::ExecDown()
shdocvw.dll!CDocObjectView::Exec()
shdocvw.dll!CBaseBrowser2::Exec()
shdocvw.dll!CWebBrowserSB::Exec()
shdocvw.dll!CWebBrowserOC::ExecWB()
iesample.exe!CMainWnd::ExtHandleCommand()
iesample.exe!CMainWnd::HandleCommand()
iesample.exe!CMainWnd::BrowseWndProc()
iesample.exe!CBrowseObj::s_BrowseWndProc()
coredll.dll!PerformCallBack4()
gwes.exe!WindowProcCallback()
gwes.exe!CWindow::CallWindowProcWInternal()
gwes.exe!MsgQueue::DispatchMessageW_I()
coredll.dll!DispatchMessageW()
iesample.exe!NewWindow()
coredll.dll!ThreadBaseFunc()
shdocvw.dll内のCDocHostUIHandler::DoTemplatePrinting()が印刷テンプレートによる印刷の実体のようだ。名前から言ってCDocHostUIHandlerクラスはIDocHostUIHandlerインターフェースの実体なのかもしれない。
デスクトップWindowsでも、IEをデバッグ起動してブレークすればスタックトレースは取れるが、OSモジュールのmapファイルが存在しないため、スタックトレースと言っても単なるアドレスの羅列でこれでははっきりいってよくわからない。
OSのmapファイルがあるだけで、スタックトレースの見通しが相当よくなるのがわかると思う。関数名がわかるだけで、だいたいの処理も推測が可能だ。WebBrowserコントロールがどのような内部クラスで実装されているかというのもおぼろげながら見えてくる。