二流エンジニアの逆襲

二流エンジニアが一流エンジニアになるまでの記録である

グローバルインスタンスのコンストラクタが呼ばれない時の対策

処理系によっては、グローバルインスタンスコンストラクタが呼ばれない場合がある。
これは、組み込み用途で使用するOSなどに多い。

今回、 TOPPERS ASP で ++ を使用するにあたって躓いたのでメモ。
TOPPERS JSPでは C++バインディングが用意されているが、 ASPでは用意されていない。よって、ユーザがC++を動作できるように、TOPPERS ASPC++ を移植する必要がある。これについては、別のエントリで説明する。


手順

リンカスクリプトの修正

gcc 4.3 以降では、 グローバルインスタンスコンストラクタは init_array セクションに設定される。
よって、リンカスクリプトで init_arrayセクションの開始アドレスと終了アドレスを取得できるようにする。
具体的には、以下のコードを追加する。

.init_array{
PROVIDE(init_array_start = .);
*(.init_array*);
*(SORT(.init_array*));
PROVIDE(init_array_end)
}

初期化ルーチンの追加

カーネルの初期化ルーチンからタスクのディスパッチが行われる前に、グローバルインスタンスコンストラクタを呼んでやる。
グローバルインスタンスコンストラクタは、先ほどのinit_array_start を用いて行う。
具体的には以下のコードを差し込む。

extern char init_array_start;
extern char init_array_end;

void init_global_ctor()
{
void (*p)() = &init_array_start;
for(;p < &init_array_end;p++)
{
(*p)();
}
}

TOPPERS ASPの場合、この関数をsta_ker()のdispatch()が呼ばれる前に実行すれば良い。



おしまい