複数のlibcを混ぜて使う

(注 : 良い子は真似しないこと。追跡の難しい問題を引き起すことが多い。)
moshMIPS移植をここしばらくメンテナンスしてないなと思い立ったので、最近の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って混ぜるとちゃんと警告が出てたような気がするが。。