個人的に最近VMWare上で開発をすることが多いのですが,VMWareにはGDB stubの機能があるのでこれを試してみようと思います.
Intel CPU, Linux上のVMware workstationで実験していますがAMDやWindows, VMWare Fusionなどでも同じようなことができるんじゃないかと思います.
設定
以下をVMの設定ファイル(<VMの名前>.vmx
)に記述します.
debugStub.listen.guest64 = "TRUE"
debugStub.hideBreakpoints = "TRUE"
debugStub.port.guest64 = "33333"
vhv.enable = "TRUE"
最初の行で64bitモードでのデバッグを指定,次の行でHWブレークポイントの利用を設定しています.ページテーブルがいろいろと変わるのでHWブレークポイントでないとうまく動かないと思います.
ポート番号は適当に設定してください. また最後はnested virtualization有効化の設定です.
GDBの実行
VMを起動後1,gdb -ex "target remote localhost:33333"
のようにしてgdbをアタッチします2.
symbol-file
コマンドでbitvisor.elf
を,directory
コマンドでBitVisorのソースディレクトリを指定してあげれば,gdb上でBitVisorのシンボルが解決できるようになります.
ここではdbgshを実行した際に呼ばれるdbgsh()
にブレークポイントを設定しています.
ゲスト上でdbgshを実行すると,ブレークポイントに引っかかってgdbに制御が移ります.
あとは普通にgdbでデバッグします.
本当はdbgshの動作を追いかけて説明しようかと思いましたが,思いの外大変そうだったのでやめました.気になる方は追って見てください.VMMCALLのレジスタ渡しで頑張って処理しています.
continue
すればゲスト側で1文字入力するたびにVMMCALLが数回発行されて処理されていることが分かります.
動作の補足
このGDB stubはどうやって動作しているでしょうか.
VMWareがL1(BitVisor)にVMENTRYするときと,L2(BitVisor上のゲスト)にVMENTRYするときでデバッグレジスタの設定を変えてVMENTRYすれば,BitVisorのみ,あるいはゲストのみをデバッグすることができそうですが,多分そんなことはしていないので,今回の場合ではゲストのLinuxが設定したブレークポイントのアドレスを利用した場合も#BPが発生すると思います.
そうするとちょっと困ってしまうわけですが,BitVisorが利用する0x40000000-0x4FFFFFFFのアドレス空間はLinuxではユーザ空間のアドレスであり,64bit環境であればそうそう衝突することはないのかなと言う気もします.
ちなみに
終了はdetach
を使います.うっかりq
でKILLするとVMが異常終了して最悪2度と起動しなくなるみたいな悲劇がおこることがあります.
-
今回はvCPU数1で実行しています.また当然ながらBitVisorは起動しておきます. ↩
-
https://github.com/cyrus-and/gdb-dashboard を利用しています. ↩