BSD

binutilsが正しく作れないことがある件

NetBSDでmingw-w64を作っていて、クロスのgccもbinutilsも出来上がったのに、それでコンパイルしたバイナリをWindowsに持っていって実行しようとすると“not a valid WIN32 application”(日本語版だと「有効なWIN32アプリケーションではありません」)などと言われる。

結論から書くと、binutilsのldのldscriptsが正しく作れていなかった。

configureでSHELLとして何故か/bin/shではなく/bin/kshが選ばれるが、このシェルだとgenscripts.sh(から呼ばれているscripttempl/pep.scなど)がエラーになる。

エラーなので止まってくれれば良いのだが、実際にはそのまま進んで、make installすると途中で打ち切られた(実質中身のない)ldscriptsがインストールされてしまう。

出来上がったgcc+binutilsを使ってコンパイルしたときに、一見すると正しいPE32(+) executableに見えるモノが出来てしまうので、なかなか原因がわからなかった。しかし、以前にも、違うパターンとはいえ同じ部分でハマったことがあったのだった。http://est.ceres.ne.jp/2008/07/02/post_241/…すぐに気がつくべきだった。

回避方法としては、binutilsのconfigureを実行する際、CONFIG_SHELL=/bin/sh …/configure …とでもすれば良い。多分。

OpenJDK7 on NetBSD

普通に pkgsrc/lang/openjdk7 動くようになってた。素晴らしい。

$ uname -srm
NetBSD 5.99.24 amd64
$ /usr/pkg/java/openjdk7/bin/java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-pkgsrc_2010_01_23_23_14-b00)
OpenJDK 64-Bit Server VM (build 17.0-b05, mixed mode)

手持ちの Java プログラムをいくつか動かしてみたが特に不具合はなし。GUI のあるプログラムは試してないが。

pkgsrc/www/ap2-fcgid

mod_fcgid の socket / shm のファイル作成場所について。
fcgid_conf.c:

#define DEFAULT_SOCKET_PREFIX "logs/fcgidsock"
#define DEFAULT_SHM_PATH "logs/fcgid_shm"

で,

        config->sockname_prefix =
                ap_server_root_relative(p, DEFAULT_SOCKET_PREFIX);
        config->shmname_path = ap_server_root_relative(p, DEFAULT_SHM_PATH);

なので,apacheもpkgsrcデフォルトのままだとすると,おそらく/usr/pkg/logs/以下になる。

で,標準でそんなディレクトリはないので,

[emerg] (2)No such file or directory: mod_fcgid: Can't create share memory for size %zu byte

といったエラーになる。

仕方がないのでhttpd.confなどで明示する。

<IfModule mod_fcgid.c>
  AddHandler fcgid-script .fcgi
  SocketPath /var/run/fcgidsock
  SharememPath /var/run/fcgid_shm
</IfModule>

SocketPathで指定するのはディレクトリで,その下にwww権限(apacheの実行権限)でソケットが作られる。
SharememPathの方はファイル名そのもの。root権限で作ってくれるようだ。

検索すると/tmp以下に置いている例もあるが,別にした方が良いと思う。

pthreadの後方非互換とpkgsrc/lang/perl5

いろいろ新しくなったついでにOSのバージョンも上げたら apache が動かなくなった(笑)。

どうも,pthread が非互換らしい。再コンパイルで解決。

…なんだけれど,perl だけ何度再コンパイルしても libpthread.so.0 をリンクした状態になる。(libpthread.so.1 だけリンクしてほしい)

ちゃんと調べていないけれど,どうも既にインストールされている /usr/pkg/lib/perl5/5.10.0/x86_64-netbsd-thread-multi/CORE/libperl.so の参照先に引っ張られている模様。インストールしてある状態で再コンパイルせずに,pkg_deleteした後に再コンパイルしたらうまくいった。

このへんの関係なのかな?

cc  -Wl,-R/usr/pkg/lib --whole-archive -shared  -L/usr/pkg/lib なんたら.o 
-o ../../../lib/auto/なんたら/なんたら.so -L../../..
 -Wl,-R/usr/pkg/lib/perl5/5.10.0/x86_64-netbsd-thread-multi/CORE
 -Wl,-R../../../lib/CORE -lperl

bge その後

NetBSDのメーリングリストで,同じBCM5722のDELLのサーバで,bgeにtso4オプションをつけているとその症状になる(tso4を外せば問題ない)と教えていただきました。やってみたら確かに正常動作。
tso4 Enable hardware-assisted TCP/IPv4 segmentation on interfaces that support it.
BCM5721なら問題ないので,BCM5722の「hardware-assist」の部分に不具合があるんですかね。

BCM5722

テキトーにBCM5755なbrgphyと同じように認識するようにmiidevsとbrgphy.cを直してみた。それらしく起動したが症状は改善せず。
テキトーすぎたのでFreeBSD, OpenBSD, Linux のソースをあたってみる。
FreeBSDとOpenBSDは,BCM5722の識別だけして,特に処理はなし。
Linux (net/tg3.c) は,BCM5722 (とBCM5756) を識別した条件分岐があるが,他の ASIC BCM5755 その他系の TG3_FLG2_PHY_JITTER_BUG フラグを立てる部分を回避してるだけ。
TG3_FLG2_PHY_JITTER_BUG がある場合の処理は,NetBSD の brgphy.c でいうところの bcm5755_load_dspcode そのもので,これを回避しているということは,結局特別な処理は何もいらないっぽい。
うーん,調子が悪いのは別の原因か。

HP ProLiant ML110 G5 で NetBSD (その2)

ネットワークまわりがどうもひっかかる感じ。

$ dmesg | grep bge
bge0 at pci4 dev 0 function 0: Broadcom BCM5722 Gigabit Ethernet
bge0: interrupting at ioapic0 pin 17
bge0: ASIC BCM5755 C0 (0xa200), Ethernet address (略)
bge0: setting short Tx thresholds
ukphy0 at bge0 phy 1: Generic IEEE 802.3u media interface

こんなNIC。
適当なPCのターミナルからsshして cat で長いファイルを流すと,最初は順調だがフロー制御が入ったあたり(?)からガタガタに(間欠的に)なる。そしてたまに,

bge0: watchdog timeout -- resetting
bge0: block failed to stop: reg 0x1400, bit 0x00000002

こんなエラーを吐く。
よくみたらukphyじゃん…。これが悪い?
ちなみに,問題の起きていないML110G4 (NetBSD 4.0_STABLE) は,こんなかんじ。

$ dmesg | grep bge
bge0 at pci3 dev 0 function 0: Broadcom BCM5721 Gigabit Ethernet
bge0: interrupting at ioapic0 pin 17 (irq 12)
bge0: ASIC unknown BCM575x family (0x4201), Ethernet address (略)
bge0: setting short Tx thresholds
brgphy0 at bge0 phy 1: BCM5750 1000BASE-T media interface, rev. 0

HP ProLiant ML110 G5 で NetBSD

NetBSD 3.x は,キーボード周りで止まる。

G4 のときは BIOS で 8042 Emulation Support を切ると起動したが,G5 はその設定が見当たらない。
NetBSD 4.x は,G5 だと起動しない。

http://mail-index.netbsd.org/port-i386/2008/11/22/msg000932.html
NetBSD 5.0_BETA は,今のところ問題なし。

current は,これから。

でまあ,G4 も G5 もなんかやたらと HDD が遅いのだが,

# dkctl wd0 setcache rw

で,普通の速さに。今は rc.local で無理やり全部のディスクを設定している。
あってるかどうかわからないけど,G4で1年間動かしたが特に問題なし。

ipfilter の keep state がうまく働かない

ipfilter で、外部からの接続をすべて拒否しつつ、内部からは何でもアリな以下のような感じの ipf.conf の設定(本当はもっといろいろ書いてあるけど)をしたとき,普通うまくいくんだけど,うまくいかないサーバが一台だけあった(NetBSD/amd64 4.0)。

block in on bge0 all
pass out quick on bge0 proto tcp from any to any 
flags S/SAFR keep state

まだちゃんと追ってないので原因はよくわからないけど、これでなおった。

ifconfig bge0 -tcp4csum

(/etc/ifconfig.bge0 で tcp4csum 指定してたので削除した)
wm とか re は tcp4csum 付きでも大丈夫っぽいんだけど、bge固有の問題?

たかがビルドでハマりにハマる

何台かでソースからビルドした NetBSD の /usr/bin/ld のうち一台だけ動かない。

$ ld
ld:built in linker script:1: ignoring invalid character `20' in expression
ld:built in linker script:1: ignoring invalid character `37777777646' in expression
ld:built in linker script:1: parse error

それぞれバージョン違いで,動かないのは netbsd-4 のツリーをビルドしたもの。netbsd-4 のバグかと思い,別のマシンにもたまたま netbsd-4 のソースが展開してあったのでビルドするとうまく動く。
あれこれやって,生成された eelf_x86_64.c がおかしいところまでは突き止めたが,何故おかしくなるかわからないので,ビルドログを比較してみると,エラーが出ているのを発見。

 #    create  ld/eelf_x86_64.c
unset MACHINE || true;  LIB_PATH=/usr/lib
/bin/sh /usr/src/gnu/usr.bin/binutils/ld/../../../dist/binutils/ld/genscripts.sh /usr/src/gnu/usr.bin/binutils/ld/../../../dist/binutils/ld /usr/lib "/usr"  x86_64--netbsd x86_64--netbsd x86_64--netbsd  elf_x86_64 /usr/lib no elf_x86_64 "x86_64--netbsd"
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory
+sed: stringify.sed: No such file or directory

その手前で stringify.sed が作られていない模様。

-#    create  ld/stringify.sed
-rm -f stringify.sed
-ln -s /usr/src/gnu/usr.bin/binutils/ld/../../../dist/binutils/ld/emultempl/astring.sed stringify.sed

で,結局あれこれいじっていると,/usr/src/gnu/usr.bin/binutils/ld/stringify.sed (シンボリックリンク)があるのを発見。既に存在するので作られないが,実行時に使われる /usr/obj/gnu/usr.bin/binutils/ld/stringify.sed がないというオチ。
結論としてはこんなかんじ。

  1. 何かの拍子に(過去に)ソースツリー内にシンボリックリンクを作ってしまった。(多分自分のミス)
  2. オブジェクトのディレクトリがソースのディレクトリとは別(NetBSD本体のビルドでは常にそうなる)であってもソース側にターゲットが存在してしまっているとオブジェクト側に作られない。(makeの仕様)
  3. ビルド中に使っている binutils/ld/genscripts.sh の中でエラーを起こしてもビルドが止まらない。(?)
  4. 結果として出来上がった eelf_x86_64.c が壊れているにも関わらず,コンパイルが通ってしまう。具体的には char * で内蔵 ldscript を返す関数が,stringify.sed がないせいで何も作られず,return; となってしまっているのにエラーにならない。(?)
  5. 存在しない戻り値(メモリのどこか)を ldscript だと思って読み込むが,当然ぐちゃぐちゃなのでエラー。

まあ発端は自分が悪いんだけど,バグで同じようなことが起きる可能性も考えると,ツール類も -Wall … -Werror つきでコンパイルできると本当はいいんだろうねえ。