ゴリ押しでgccにてMakeを通す
id:higepon氏が発足し今尚開発が行われている、自作OS界隈では云わずと知れたMonaOS - Free Operating Systemですが、そのLinux上におけるtoolchainにはMINGWが使用されています。
そこで、GNU toolchainによってMakeを無理やり通してみた結果、何とか起動し動作が確認できたので、ざっくばらんに手順を記録しておきたいと思います。
はじめに
前提として以下の緩いルールを設けました。
- 実行形式
- PEフォーマット、圧縮形式はナシ(.BIN と .ELF のみ)
- ライブラリ
- 共有ライブラリはナシ(全てstaticリンク)
- アセンブラ
- nasmを使用する(gasへの変換はしない)
また、今回の環境は以下の通りです。
Mona | mona-0.3.0alpha9 |
Host | colinux-2.6.12-co-default |
GCC | 4.1.2(Debian 4.1.1-21) |
share/configs
GNUのldのリンカスクリプト取得(User用)
- --verboseオプションにて。ファイル名はmonapi.ldsとする
- syntax errorになるような先頭数行と最終行は削除、またはコメントアウト
- __executable_start と SIZEOF_HEADERS への値をカレントアドレス(.)へと修正
- PROVIDE (__executable_start = .); . = SIZEOF_HEADERS;
- .ctorセクションに、__CTOR_LIST__、__CTOR_END__とフラグ(0xFFFFFFFF/0)を定義
__CTOR_LIST__ = .; LONG(-1); …コンストラクタの定義… LONG(0); __CTOR_END__ = .;
- .dtorセクションも同様に__DTOR_LIST__、__DTOR_END__とフラグ(0xFFFFFFFF/0)を定義
Makefile.inc
Makefile.incはconfigureスクリプトにて生成されるので一旦、MINGWとしてconfigureスクリプトをトップディレクトリにて実行します。
% ./configure --mingw-prefix=/usr/bin/i586-mingw32msvc-
生成されたMakefile.incを以下のように修正しました。
monapi-bin.inc
- .cppサフィックスルール
- g++へのオプションに -fno-use-cxa-atexitを追加
- TARGETルール
- ldに-Tオプションでmonapi.ldsを指定
- -T $(SHAREDIR)/configs/monapi.lds
- ldに-Tオプションでmonapi.ldsを指定
-fno-use-cxa-atexit指定しない場合、__static_initialization_and_destruction_0関数がリンクされて、その関数内で参照している __dso_handletと__cxa_at_exitが無いと文句を言われてしまうためです。
2007-02-03 - memologueにて詳細な解説がなされています。
core/kernel
Makefile
- ldに-Tオプションでkernel.ldsを指定
- -T $(SHAREDIR)/configs/kernel.lds
core/monalibc
Makefile
- TARGET変数定義 に += で $(CRT_OBJECT)を追加
- BUILD_TARGET=ELFだと追加されてないため
- LINK変数定義の-lmonapi-imp を -lmonapi に変更
- g++のオプションに以下を追加
-nostdinc -nostdlib -fno-exceptions -fno-rtti -fno-strict-aliasing
-
- gxx_personarity_v0エラーが出るため
core/monapi
Makefile
- installターゲットに$(CRT_OBJECT)を追加
_alloca.asm
- シンボルの _ プレフィックス削除
messages.cpp
- server_names の ".BN5"、".EX5" を ".BIN"、".ELF" に変更
core/shell_server
Makefile
- BUILD_TARGET=ELF であった場合のinclude文を monapi-el5.inc から monapi-elf.inc へ
main.cpp
- LookupMainThread("SCREEN.EX5")の引数を"SCREEN.ELF"に指定
Shell.cpp
- commandExecuteでコマンドライン処理している辺りの name + ".EX5" や command + ".EX5" を ".ELF" に
core/monitor_server
main.cpp
- すべての ".BN5" と ".EX5" を ".BIN"、".ELF"に
core/keyboard_server
Makefile
- BUILD_TARGET=ELF であった場合のinclude文を monapi-el5.inc から monapi-elf.inc へ
- ADDLINK変数定義の-lmonalibc-imp を -lmonalibc に変更
core/screen_server
Makefile
- BUILD_TARGET=ELF であった場合のinclude文を monapi-el5.inc から monapi-elf.inc へ
core/mouse_server
- screen_serverと同様
core/pe_server
Makefile
- include文を monapi-bn5.inc から monapi-bin.inc へ
tool/mkimg
MONITOR.CFG
- すべての ".BN5" と ".EX5" を ".BIN"、".ELF"に
- PEサーバとSCHEMEサーバの行をコメントしそれ以外は有効に
AUTOEXEC.MSH
- testプログラム自動実行文を追加(バナー出力後あたりに)
- @EXEC /APPS/TEST.APP/TEST.ELF
include/sys
types.h
- 以下の定義を追記
#define __fastcall __attribute__((__fastcall__)) #define __declspec(x) /* */
Makeと実行
ソーストップディレクトリで以下を実行
% make % cd tool/mkimg % qemu -L /usr/share/qemu -m 128 -fda mona.img -no-kqemu -nographic -cdrom mona.iso -boot d -serial stdio
すると、printfしている内容が文字単位で<>で囲まれて出力されると思います。
グラフィック出力のないcolinuxでの動作確認のためグラフィック出力を無効(-nographic)にしています。*1
出力可能な環境であれば、-nographicを外すとシェルが動くはずです…。