ld-elf.so.2 がうまくビルドできない

ソースとってくる

git clone git://git.dragonflybsd.org/dragonfly.git
git checkout v2.6.3

コンパイルしてインストール。

cd lib/libc_rtld
make
cd ../../libexec/rtld-elf
make
cp ld-elf.so.2 /usr/libexec

こうするとほとんど全てのプログラム(ようするに dynamic link なプログラム)が SEGV するようになる。 元の ld-elf.so.2 に戻してやるとOK。
core を探っても 0x00000 resident_start にこけている。これは ld-elf.so.2 の中でこけているんですよねぇ…。

いろいろ試してみる。

file /usr/libexec/ld-elf.so.2 ld-elf.so.2
ld-elf.so.2:              ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), statically linked, not stripped
/usr/libexec/ld-elf.so.2: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped

手元のは "statically linked" になっているけどなにか関係が…?

gcc のバージョンなど。

Target: i686-gentoo-dragonfly2.6
Configured with: /home/tmp/portage/sys-devel/gcc-4.4.3-r2/work/gcc-4.4.3/configure --prefix=/usr --bindir=/usr/i686-gentoo-dragonfly2.6/gcc-bin/4.4.3 --includedir=/usr/lib/gcc/i686-gentoo-dragonfly2.6/4.4.3/include --datadir=/usr/share/gcc-data/i686-gentoo-dragonfly2.6/4.4.3 --mandir=/usr/share/gcc-data/i686-gentoo-dragonfly2.6/4.4.3/man --infodir=/usr/share/gcc-data/i686-gentoo-dragonfly2.6/4.4.3/info --with-gxx-include-dir=/usr/lib/gcc/i686-gentoo-dragonfly2.6/4.4.3/include/g++-v4 --host=i686-gentoo-dragonfly2.6 --build=i686-gentoo-dragonfly2.6 --disable-altivec --disable-fixed-point --without-ppl --without-cloog --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-libmudflap --disable-libssp --disable-libgomp --enable-cld --with-python-dir=/share/gcc-data/i686-gentoo-dragonfly2.6/4.4.3/python --disable-libgcj --with-arch=i686 --enable-languages=c,c++ --enable-shared --enable-threads=posix --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.4.3-r2 p1.2'
Thread model: posix
gcc version 4.4.3 (Gentoo 4.4.3-r2 p1.2)

CC=/usr/libexec/cc make しても変わらず。 (/usr/libexec/cc は多分 DragonFly の元のコンパイラ)

とりあえず dynamic linker にカレントディレクトリのものを使った ELF バイナリを作る。 hoge.c は "int main { return 0; }" これだけ。

gcc hoge.c -ggdb -Wl,--dynamic-linker=./ld-elf.so.2

gdb で実行すると多少の back trace がとれる

Program received signal SIGSEGV, Segmentation fault.
0x2804b5a2 in ?? ()
(gdb) bt
#0  0x2804b5a2 in ?? ()
#1  0x28049e07 in ?? ()
#2  0x28049b62 in ?? ()

この時に ps aux|grep a.out で a.out の process number 調べて /proc//maps を見てやる。

08048000-08049000 r-xp 00002000 00:00 328124     /home/gentoo/dragonflybsd/libexec/rtld-elf/a.out
08049000-0804a000 rw-p 00002000 00:00 328124     /home/gentoo/dragonflybsd/libexec/rtld-elf/a.out
0804a000-0804b000 rw-p 00001000 00:00 0
28049000-28070000 r-xp 0007c000 00:00 328132     /home/gentoo/dragonflybsd/libexec/rtld-elf/ld-elf.so.2
28070000-28072000 rw-p 0007c000 00:00 328132     /home/gentoo/dragonflybsd/libexec/rtld-elf/ld-elf.so.2
28072000-2807e000 rw-p 00014000 00:00 0
2807e000-28086000 rwxp 00014000 00:00 0
bfbe0000-bfc00000 rwxp 00020000 00:00 0     [stack]

0x2804b5a2 - 0x2804900 = 0x25a2 である。 nm ld-elf.so |sort してみると

00002323 t init_dag
000023b4 t init_dag1
00002447 t init_rtld
000025af t initlist_add_neededs
00002600 t initlist_add_objects

なので、多分 init_rtld の中で落ちているのでしょうよ。

実際、 init_rtld() の中で assert(0==1); をしかけてやるとどこで落ちているかどうか判定できます。

結局、このアクセスの部分で落ちていて。

    r_debug.r_brk = r_debug_state;
    r_debug.r_state = RT_CONSISTENT;
% nm ld-elf.so.2|grep r_debug
00034988 B r_debug
0000429a T r_debug_state

0x28049000 + 0x00034988 = 0x2807d988 で map されてない領域? BSS だからそれはいいのかな???

よくわかりません。助言いただけるとうれしいです。