複数のlibcを混ぜて使う
(注 : 良い子は真似しないこと。追跡の難しい問題を引き起すことが多い。)
moshのMIPS移植をここしばらくメンテナンスしてないなと思い立ったので、最近のmoshをビルドしてFonera(無線LANルータ)で動かすことにした。もっとも、moshはかなりメモリを食うので、swap用のHDDを接続できない環境ではあまり健全に動かないだろう。。Fonera 2はUSB経由でHDDを接続できるので、それを利用することにした。
で、Foneraで動くLinuxディストリビューションとして一般的なのはOpenWrtであり、OpenWrtのlibcはuClibcを採用している。これは一般的なeglibcとかglibcとはABI互換ではなく、専用の実行環境を作る必要がある。
moshはuClibcでは正常にコンパイルできないので、eglibcかglibcな開発環境を準備する必要がある。幸い、OpenWrtはtrunkを使うことでこれらの開発環境も完全に自動的に作ることができる。
ダイナミックリンカのインストール
重要なのは、uClibcとeglibcではダイナミックリンクを行うリンカが異なることで、これだけはシステムにインストールする必要がある。
ダイナミックリンカのパスはreadelf -lで読みとることができる。(gccに対応したreadelfを使うこと。ここでは、mips-linux-readelf。)
prism:mips oku$ mips-linux-readelf -l ./nmosh Elf file type is EXEC (Executable file) Entry point 0x418560 There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x00400034 0x00400034 0x00120 0x00120 R E 0x4 INTERP 0x000154 0x00400154 0x00400154 0x0000d 0x0000d R 0x1 [Requesting program interpreter: /lib/ld.so.1]
この例では、/lib/ld.so.1が該当する。これを適当なところからコピーしてくる必要がある。通常のシチュエーションでは、これはコンパイルに使用したgccのアーキテクチャ名の場所にある。mips-linux-gccが/opt/build/binにあるなら、ld.so.1は、/opt/build/mips-linux/lib/ld.so.1にある筈。
ついでに他の.soもコピーするのが望ましいが、ld.so.1以外のライブラリはLD_LIRBARY_PATHで場所を指定することができる。
root@rain:/mnt/sda3/oku# ls libc.so.6 libdl.so.2 libgcc_s.so.1 libgmp.so.10 libm.so.6 libpthread.so.0 libstdc++.so.6 nmosh root@rain:/mnt/sda3/oku# LD_LIBRARY_PATH=. HOME=. ./nmosh GC Warning: Repeated allocation of very large block (appr. size 528384): May lead to memory leak and poor performance. nmosh top program nmosh> (display (+ 1.2 3.4)) 3.5295486008178236#<unspecified> nmosh>
浮動小数点の演算がおかしいなど、まだ微妙な問題があるが一応動作する。多分FPUの無い環境でmoshを使っているのが原因だろう。追記 : gccをビルドするときにsoft-floatにするのを忘れていた。。
prism:~ oku$ mips-linux-gcc -v Using built-in specs. COLLECT_GCC=mips-linux-gcc COLLECT_LTO_WRAPPER=/opt/moshbuild/libexec/gcc/mips-linux/4.5.0/lto-wrapper Target: mips-linux コンフィグオプション: ../gcc-4.5-20100211/configure --target=mips-linux --prefix=/opt/moshbuild --enable-languages=c,c++ --with-float=soft スレッドモデル: posix gcc version 4.5.0 20100211 (experimental) (GCC) prism:~ oku$
ちゃんと--with-float=softを付ければ健全に動いた。しかし、soft-floatとhard-floatって混ぜるとちゃんと警告が出てたような気がするが。。