2007年1月12日金曜日

(FreeBSD ports/lang/gcc42) /usr/bin/ld: .libs/jv-convert: hidden symbol `__eprintf' in ...lang/gcc42/work/build/./gcc/libgcc.a(_eprintf.o) is referenced by DSO

Problem summary



ports/lang/gcc42 cannot build with following error messages.



/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/gcj -B/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/ -B/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/ -ffloat-store -fomit-frame-pointer -g -O2 -o .libs/jv-convert --main=gnu.gcj.convert.Convert -shared-libgcc -pthread  -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/.libs ./.libs/libgcj.so -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src/.libs -lz -L/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc -lgcc_s -lgcc_s -Wl,--rpath -Wl,/usr/local/lib/gcc-4.2.0
/usr/bin/ld: .libs/jv-convert: hidden symbol `__eprintf' in /home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/libgcc.a(_eprintf.o) is referenced by DSO
collect2: ld returned 1 exit status
gmake[3]: *** [jv-convert]  1
gmake[3]:  `/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava'
gmake[2]: *** [all-recursive]  1
gmake[2]:  `/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava'
gmake[1]: *** [all-target-libjava]  2
gmake[1]:  `/home2/ports.work/usr/ports/lang/gcc42/work/build'





OS version

FreeBSD 5.5-STABLE.

Some FreeBSD 6.2-PRERELEASE could build ports/lang/gcc42 and others did not.



How to fix

# pkg_delete gcc-2.95.3_2



Problem details



unresolved __eprintf symbol was included in libgcj.a



# nm .libs/libgcj.a | grep eprintf
         U __eprintf
         U __eprintf



this came from ltdl.o and mprec.o



ltdl.o:
000000a3 r .LC9
         U _CurrentRuneLocale
         U _GLOBAL_OFFSET_TABLE_
         U ___runetype
         U __eprintf



mprec.o:
00000157 T _Jv_ulp
         U __eprintf





# find . -name ltdl.o -print
./libltdl/.libs/ltdl.o
./libltdl/ltdl.o



libltdl/ltdl.o:
         U _CurrentRuneLocale
         U ___runetype
         U __eprintf
         U __isthreaded
         U access





ltdl.o was build like this



# /bin/sh ./libtool --debug --tag=CC --mode=compile /home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/xgcc -B/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/ -B/usr/local/i386-portbld-freebsd5.5/bin/ -B/usr/local/i386-portbld-freebsd5.5/lib/ -isystem /usr/local/i386-portbld-freebsd5.5/include -isystem /usr/local/i386-portbld-freebsd5.5/sys-include -DHAVE_CONFIG_H -I. -I../../.././..//gcc-4.2-20070102/libjava/libltdl -I. -O2 -O -pipe -march=pentiumpro -c -o ltdl.lo ../../.././..//gcc-4.2-20070102/libjava/libltdl/ltdl.c



Looking into /usr/local/i386-portbld-freebsd5.5/include, __eprintf symbol can be found.



# grep -R eprintf /usr/local/i386-portbld-freebsd5.5/include
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf (const char *, const char *, unsigned, const char *)
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf (const char *, const char *, unsigned, const char *)
/usr/local/i386-portbld-freebsd5.5/include/assert.h:  (__eprintf ("%s:%u: failed assertion `%s'\n",             \
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf () __attribute__ ((noreturn)); /* Defined in libgcc.a */
/usr/local/i386-portbld-freebsd5.5/include/assert.h:  (__eprintf ("%s:%u: failed assertion `%s'\n",             \



Hummmm...



# ls -l /usr/local/i386-portbld-freebsd5.5/include/assert.h
-rw-r--r--  1 root  wheel  1486 11  9 14:41 /usr/local/i386-portbld-freebsd5.5/include/assert.h
# pkg_which  /usr/local/i386-portbld-freebsd5.5/include/assert.h
gcc-2.95.3_2





There is one more problem about ports/lang/gcc42



Problem summary



ports/lang/gcc42 cannot build binary package.



===>  Building package for gcc-4.2.0_20070102
Creating package /usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz
Registering depends: mpfr-2.2.1 libiconv-1.9.2_2 libgmp-4.2.1_1.
Creating bzip'd tar ball in '/usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz'
tar: bin/jar42: Could not stat: No such file or directory
pkg_create: make_dist: tar command failed with code 256
*** Error code 1



Stop in /usr/ports/lang/gcc42.



How to fix



a very simple workaround is ...



# touch /usr/local/bin/jar42



# make package
===>  Building package for gcc-4.2.0_20070102
Creating package /usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz
Registering depends: mpfr-2.2.1 libiconv-1.9.2_2 libgmp-4.2.1_1.
Creating bzip'd tar ball in '/usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz'



---------------------------------------------------



というわけで、FreeBSDのportsで、lang/gcc42をビルドしようとしたら(別にgcc-4.2が使いたいわけじゃなくて、portupgradeしたときに、依存関係によって、gcc42がビルドされただけなんですが)、エラーがでて失敗しました。



/usr/bin/ld: .libs/jv-convert: hidden symbol `__eprintf' で検索すると



http://lists.freebsd.org/pipermail/freebsd-questions/2007-January/138706.html



lang/gcc41 woes



というのが見つかりますが



hidden symbol `__eprintf' で検索すると、もっとたくさんでてくるようです。



で、いろいろ見てみましたが、解決方法は見つかりませんでした。



仕方ないので、自分で調べてみたよ、ってかんじ。



調べてみた結果、ports/lang/gcc295でインストールされるassert.hに含まれるシンボル__eprintfが悪さをしているのが原因でした。gcc42とgcc295がconflictしてる、っていってもいいかもしれませんが、gcc295のassert.hのインストール先がおかしいんじゃない?っていう気もします。



問題の解決方法をどうやって見つけたか?



かなり泥臭い方法ですが・・・





エラーを出したコマンドが



/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/gcj -B/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/ -B/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/ -ffloat-store -fomit-frame-pointer -g -O2 -o .libs/jv-convert --main=gnu.gcj.convert.Convert -shared-libgcc -pthread  -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/.libs ./.libs/libgcj.so -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src/.libs -lz -L/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc -lgcc_s -lgcc_s -Wl,--rpath -Wl,/usr/local/lib/gcc-4.2.0



だったので、これの頭に、「ktrace」をつけて実行しました。ようするに、どのファイルを参照しているのか、を知りたかったのです。しかし、残念ながら、途中でexecしてしまうようで、ktraceで追いかけられません(私が子プロセスのトレース方法を知らないだけ?)。



ただ、何をexecしたかはktraceでわかるので、execしているプログラムを、ktraceで実行するようにwrapper scriptを作成します。さらにexecしてれば、同じことの繰り返し。



そうやってわかったのですが



/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/collect2 が呼ばれていて、



さらに



/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/collect-ld



が呼ばれてました。で、collect-ldの中身はというと



# cat /home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/collect-ld
#!/bin/sh
exec /usr/bin/ld "$@"



なんてものだったので、ここ「ld --verbose」と書き換えてしまいます。



exec /usr/bin/ld --verbose "$@"



さらにexecの行の前に、



echo /usr/bin/ld "$@"



とか付けたすのもいいかもしれません。



これで、実際にどのファイル(ライブラリ)をリンクするかが表示されるようになるので、あとは、アクセスしたファイルすべてについて、「grep __eprintf」をしまくります。



そうやってみつけたのが、libgcj.aでした。



ktraceしたのは、grepでの探索範囲を狭めるという目的があったからでして、grep -Rで手当たりしだいに探すのでも、いいかもしれません(時間がかかるかもしれませんが)。



libgcj.aに取り込まれたltdl.oに、__eprintfというunresolved symbolがあることが、nmコマンドですぐにわかりますから、あとは、ltdl.oがどうやってコンパイルされたかを、調べればいいってこと。コンパイル中のログをみてもいいし、ログを残していなければ、ファイルを削除してから、gmakeコマンドを実行しちゃえばいいです。



/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/xgcc -B/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/ -B/usr/local/i386-portbld-freebsd5.5/bin/ -B/usr/local/i386-portbld-freebsd5.5/lib/ -isystem /usr/local/i386-portbld-freebsd5.5/include -isystem /usr/local/i386-portbld-freebsd5.5/sys-include -DHAVE_CONFIG_H -I. -I../../.././..//gcc-4.2-20070102/libjava/libltdl -I. -O2 -O -pipe -march=pentiumpro -c ../../.././..//gcc-4.2-20070102/libjava/libltdl/ltdl.c -o ltdl.o



というコマンドでコンパイルされているので、じゃあ、includeファイルのどこかに__eprintfがあるに違いない、となるので、include pathにあるディレクトリについて、grep -Rしまくったところ



% grep -R eprintf /usr/local/i386-portbld-freebsd5.5/include
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf (const char *, const char *, unsigned, const char *)



というかんじで見つかりました。



このヘッダファイルはどこからやってきたのか、どのパッケージでインストールされたのかは、pkg_whichでわかります。



# pkg_which  /usr/local/i386-portbld-freebsd5.5/include/assert.h
gcc-2.95.3_2



なーんだ、じゃあ、gcc-2.95.3_2をpkg_deleteしちゃえばいいんじゃない?



というかんじです。



0 件のコメント:

コメントを投稿