makeするとconfigureが実行された後、tools/scripts内のビルドスクリプトが走る。libcxx,newlib,libbfcのコードを取ってきてbareflank_gcc_wrapper.shという独自のgcc/clangスクリプトでビルドする。 まず最初にsetup_(deist).shでディストロ別にdockerとかgcc/clangを落としてくる。 次にsetup_build_environmentで./configureが走って終わり。 bareflank_gcc_warpper.shはローカルじゃないとdocker runでホストと同じパスでコンパイル。docker imageはbareflank/compilerという名前でtools/dockerfilesにdockerfilesがある。 各ライブラリのビルドはソースコードを持っている物(bfcrt,bfunwindなど)はcommon/common_(subdir|target).mkを埋め込んでmakeする。これらは要はテンプレートになっていてsubidrはbin,test以外のディレクトリのmakeをする。srcのなかのMakefileはtarget.mkがあってそいつが実質的なmakeの処理。 MakefileはMakefile.bfからBUILD_ABS/makefilesにテンプレート置換などしてからコピーされる。ルートのMakefileからmake -c BUILD_ABS/makefilesすることでビルド開始。
newlibを基本使ってるが、malloc,init/fini,pthreads,syscallだけ独自実装をやってる。(該当関数はnewlibにパッチをあてて#if 0で除去している) libc(newlib)とlibbfc(独自実装部分)をリンク。
ホストOSにロードされるbfdriver自体はカーネルモジュールでC言語で書かれている。ioctlでbfm(mangaer)とやり取り。つまりKVM的なアーキテクチャになっている。 基本的にlibc++含めライブラリは独自のELFローダが動的にロードする。 これらのロードはVMM起動時、つまりbfdrivers/common.cのcommon_load_vmmで行われる。 local_initなどもここで実行されている。ELFローダー自体はC言語で書かれていてカーネル空間に対応させただけ(?)
ロードするモジュールの登録とかはioctlでやってる。ioctlはbfmがラップしていて例えばVMMロード時に一緒にロードしたいライブラリの登録などはcall_ioctl_add_moduleで行う。VMM起動時に最初にロードするモジュールはbfm/bin/native/vmm.modulesに定義されている。
まとめるとBareflankは以下の手順で動く。 まずbfmか何かでbfdriver entry point(kernel module)にioctlを発行してstartさせる。bfdriverはハイパーバイザ本体bfvmmやbfvmmが依存しているC++ライブラリ達を独自のELFローダーでロードしてlocal_initなどを実行する仕組み。