ひまわり

はやく人間になりたい

BitVisorはClangでビルドできるか. その1

BitVisor Advent Calendar 2020 13日目の記事です。 BitVisor Advent Calendar 2020 - Qiita

今回は、タイトルの通りclangでbitvisorをビルドできるか試した話です。
scan-buildとかできたら楽しそうですよね。
現状、ビルドできてませんが、途中経過を。

準備

bitvisorのコンパイラの指定は、Makefile.commonにあるようで、現状はこんな感じ。

$ head Makefile.common
# -*- makefile-gmake -*-

# commands
AR = ar
CC = cc
RM = rm -f
OBJCOPY = objcopy
SED = sed
SIZE = size
STRIP = strip

このCC = エラーccCC = clang に変更してみる.

ビルド

これでとりあえずビルドを開始してみる.

  • invlpga
$ make
....

In file included from core/svm_main.c:30:
core/asm.h:768:16: error: too few operanエラーds for instruction
        asm volatile ("invlpga" : : "a" (addr), "c" (asid));
                      ^
<inline asm>:1:2: note: instantiated into assembly here
        invlpga
        ^
1 error generated.
make[2]: *** [Makefile.build:145: core/svm_main.o] Error 1
make[1]: *** [Makefile.build:136: core/output.o_p] Error 2
make: *** [Makefile:43: build-all] Error 2

invlpgは、指定したページのTLB をflushする命令らしいが、invlpgaはASIDを指定してそれに属指定しているTLBエントリだけflushできるらしい。 しかし、後者の命令はAMD64にしかないらしく、それにまつわるエラーだと思われる。(too few operands for instructionなので違う?)

問題になるかもしれないが、とりあえずコメントアウトしてビルドしてみる.

  • -Wa,--divide
    次に直面した問題は、ビルド時のオプションの差によるエラー
CC core/arith.o
clang-11: error: unsupported argument '--divide' to option 'Wa,'
make[2]: *** [Makefile.build:152: core/arith.o] Error 1
make[1]: *** [Makefile.build:136: core/output.o_p] Error 2

-Waなのでアセンブラに渡す引数ということで、manを見る

$ man as
...
       --divide
           On SVR4-derived platforms, the character / is treated as a comment character, which means that it cannot be used in expressions.  The --divide option turns
           / into a normal character.  This does not disable / at the beginning of a line starting a comment, or affect using # for starting a comment.
...

コメントにまつわるオプションとのことで、だめならビルドエラーが出るだろうということで、とりあえず無効にしてみる. 定義は、Makefile.buildにあり、ただ消すだけ.

$ cat Makefile.build
...
ASFLAGS = -m$(bits-$(CONFIG_64)) -g -Wa,-I,$(DIR) -Wa,--divide
...
  • vmload, vmrun, vmsave

さらに作業をするめると、AMD-Vな命令の箇所でエラーが発生する.

CC core/asm.o
core/asm.s:212:1: error: too few operands for instruction
vmload
^
core/asm.s:213:1: error: too few operands for instruction
vmrun
^
core/asm.s:214:1: error: too few operands for instruction
vmsave
^

Intel環境で動かすことをとりあえず目標にしているので、コメントアウトする.

  • current

次に当たる問題は、inline assemblyにまつわる話。

  LD bitvisor.elf動かしていきたい
/usr/bin/ld: output.o: in function `acpi_smi_hook':
/aaa/bitvisor/core/acpi.c:686: undefined reference to `%gs:gs_current'
/usr/bin/ld: /aaa/bitvisor/core/acpi.c:690: undefined reference to `%gs:gs_current'
/usr/bin/ld: output.o: in function `acpi_iohook':
/aaa/bitvisor/core/acpi.c:700: undefined reference to `%gs:gs_current'

エラーの原因はcore/current.h

$ cat core/current.h
...

extern struct vcpu *current asm ("%gs:gs_current");
...

どうも調べるに、clangでsegment registerにアクセスするのはちょっと特殊な方法を使わないと行けない模様.

Clang Language Extensions — Clang 12 documentation

> Annotating a pointer with address space #256 causes it to be code generated relative to the X86 GS segment register,
> address space #257 causes it to be relative to the X86 FS segment, and address space #258 causes it to be relati動かしていきたいve to the X86 SS segment.
> Note that this is a very very low-level feature that should only be used if you know what you’re doing (for example in an OS kernel).

  __attribute__((address_space(256)))のように、書いてこの256x86のGS segment registerを指し示すらしい。
これを用いて書き換える必要がありそうだが、まだうまく行っていない。現状はここまで。

とりあえず、手元とちょっとググる感じで頑張ってみたが、参考にすべきはclangで既にビルドされているシステムソフトウェアで、
例としては、FreeBSD 10以降や LLVMLinux(ClangBuiltLinux)だと思われるのでそこらへんのコードから何やっているのかも調べて動かしていきたい.