BitvisorのINITFUNCマクロの読解に挑戦

昨日の日記みたいに、「生のコードを読んで、分からないところを調べる」というアプローチは勉強する上で結構有効な気がしたので、今日もチャレンジ。

今日はBirvisorのコードです。Bitvisorのコードには、以下のマクロがたくさんでてきます。

 //core/time.c
 158INITFUNC ("global3", time_init_global);

えー、何これ。というわけで、追ってみます。すると、core/initfunc.hに正体があることが分かります。

 //core/initfunc.h
  33#define INITFUNC(id, func) struct initfunc_data __initfunc_##func \
  34        __attribute__ ((__section__ (".initfunc"), aligned (1))) = { id, func }

あー!早速昨日の引数付きマクロの小技が使われてますね!

__section__(".initfunc")とありますから、.initfunc セクションにデータを置くマクロである、ということが分かります。さて、.initfuncセクションはどこにあるんでしょうか? core/initfunc.cを見ると、

 //core/initfunc.c
  35extern struct initfunc_data __initfunc_start[], __initfunc_end[];

となっており、コンパイラに「initfuncセクションに配列としてアクセス」できるように宣言されていることが分かります。でも、extern宣言されていますから、このファイルの中に実体の宣言はありません。ということは、リンカスクリプトの中でリンク時に宣言しているのかなぁと思ってみると

 bitvisor.lds
  17        .data : AT (phys + (data - head)) {
  18                data = .;
  19                *(.data)
  20                . = ALIGN (8);
  21                __initfunc_start = .;
  22                *(.initfunc)
  23                __initfunc_end = .;
  24        }

お!ドンピシャです。dataセクションに置かれているんですね。つまり、マクロINITFUNC(id,func)は「__initfunc_##funcという名前の変数宣言である」ということがわかります。

残っている謎

aligned (1) って効果あるのだろうか。1バイト境界に合わせて設置するってことだよね?x86のメモリアクセス幅は最低でも1バイト幅のはずなので、なくても同じコードを吐きそうそうな気がするんだが...。実験してみっかー。