mrtska.net

VirtualBoxのビルトインデバッガを使いたい


Posted at:

この記事は自作OS Advent Calendar 2018 第15日目の記事です。

はじめに

この記事は、一般に自作OSをする人と言えばLinuxでvimでゴリゴリコーディングしてqemuでデバッグしているイメージがあります(個人の感想です)が、qemuもいいけどVirtualBoxも良いぞという記事です。

本編

VirtualBoxには、あまり知られていない(?)ビルトインデバッガが存在します。

デフォルトではもちろんOFFになっているのでこいつをONにしてみたいと思います。

環境変数に VBOX_GUI_DBG_ENABLEDVBOX_GUI_DBG_AUTO_SHOW をtrueに設定します。

image.png

追加した後、VirtualBoxを再起動するとメニューバーに デバッグ が出現します。

image.png

image.png

この画像では、boot endのところで

while(1) asm volatile("hlt");

と、してあるので割り込みが起きない限りレジスタは変動しません。

そこでデバッガのコマンドラインに rg というゲストOSのレジスタを表示するコマンドを叩きました。

お気づきの方もいるかもしれませんが、レジスタが64bitになっているということは boot endの時点でこのカーネルはロングモードになっています。

ロングモードにする前に rg コマンドを叩くとeax, ebx等32bitのレジスタが表示されます。

また、db, dw, dd, dq コマンドを使うと指定した仮想アドレスをダンプする事ができます。

上の画像のrbxレジスタは 0x104000 なので試しに見てみます。

VBoxDbg> dq 104000
%0000000000104000: 00000000000001e3 0000000000000000
%0000000000104010: 0000000000000000 0000000000000000
%0000000000104020: 0000000000000000 0000000000000000
%0000000000104030: 0000000000000000 0000000000000000
%0000000000104040: 0000000000000000 0000000000000000
%0000000000104050: 0000000000000000 0000000000000000
VBoxDbg> 

どうやら 0x01E3 のようです。

dpコマンドで指定した仮想アドレスが、ページングによって物理アドレスとマッピングされていない場合はエラーで値を読むことは出来ません。

そりゃそうですよね。

マルチプロセッサのパソコンを起動した際に一番最初に起動するプロセッサをBSP(ブートストラッププロセッサ)と呼びますが、BSPじゃないプロセッサ(アプリケーションプロセッサ)のレジスタを見たい場合は cpu {apic_id} で表示するCPUを変更する事ができます。

他にも、指定した仮想アドレスをディスアセンブルする u コマンドや 各種IO機器の情報を見れる info コマンドなど自作OSをする際に役立つコマンドが結構あります。

これはIO APICの状態を出力したものです。

VBoxDbg> info ioapic
I/O APIC at 0xfec00000:
  ID                      = 0x0
    ID                      = 0x0
  Version                 = 0x170020
    Version                 = 0x20
    Pin Assert Reg. Support = false
    Max. Redirection Entry  = 23
  Current index           = 0x0
  I/O Redirection Table and IRR:
  idx dst_mode dst_addr mask irr trigger rirr polar dlvr_st dlvr_mode vector
   00   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   01   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   02   phys      00     1    1   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   03   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   04   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   05   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   06   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   07   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   08   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   09   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   10   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   11   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   12   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   13   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   14   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   15   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   16   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   17   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   18   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   19   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   20   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   21   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   22   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
   23   phys      00     1    0   edge    0   acthi  idle     Fixed      0 (0000000000010000)
VBoxDbg> 
`

今は特に何も設定されていませんが、割り込み周りを扱う際は非常に役に立ちそうです。

調べてみたところ、infoコマンドは他には APIC、AHCI、APIC Timer、cpuid、IO Port、MM I/O、xhci等のUSBコントローラ、PCIなどいろいろな低レイヤーな情報が見れるようです。

これらの機能を知ったのは実は自作OSを始めてからだいぶたった後で、もっと早く知りたかった・・・と大分落胆した記憶があります。

終わりに

ここまでVirtualBoxのビルトインデバッガについて書いてきましたが、qemuで良いじゃんと思った方もいらっしゃるのでは?と思います。

実際qemuで似たようなことはほぼほぼ出来そうな気がしますが、qemuで動いてVirtualBox等の他の仮想マシンで動かないというのは自作OSでは割とよくある話ではないかと思います。

私は最近はあまりやれていませんが、一番やっていた時にはVirtualBoxとVMware Workstationで自作OSを動かしていました。VirtualBoxでは動くのにVMwareではダメといったことがたまにあり四苦八苦したのも今ではいい思い出です。

今はもう手元にありませんが、BIOSブートのDynabookもたまに使っていました。

仮想マシンでの開発も楽しかったですが、Dynabookという実機で実際にキーボード割り込みを受け取って画面に表示出来た時は本当に面白かったです。

あとはVirtualBoxでFreeType2を使ってフォントをレンダリング出来た時でしょうか。

既存のものを使うにはシステムコールなどをLinuxに合わせる必要が出て来ますが日本語が表示できた時の達成感はすごかったです。さすがにDynabookはIntel HD Graphicsを叩く必要があったので諦めましたが・・・

カーニングとかベースラインとかがガバガバですが楽しかったです。

この楽しさがいろいろな方に伝われば良いなと思いつつ、記事はこの辺にしたいと思います。

参考

12.1.3. The built-in VM debugger https://www.virtualbox.org/manual/ch12.html#ts_debugger


Tag: 自作OS


Comment