さすがにここまでか?

kik@as305:~/work/codegolf/hello$ ls -l tiny-hello.bin 
-rwxr-xr-x  1 kik users 59 2006-11-10 08:35 tiny-hello.bin
kik@as305:~/work/codegolf/hello$ ./tiny-hello.bin || echo error
Hello, world!
kik@as305:~/work/codegolf/hello$ 

「!」をとると1B縮むから、http://www.muppetlabs.com/~breadbox/software/tiny/ にあるのより短くなった。

S: _start
P: phdr addr
o: file addr
V: virt addr
s: file size
m: virt size

P=+4
00          04          08          0C          10          14          18          1C          20          24          28          2C          30
7f 45 4c 46 ** ** ** ** ** ** ** ** ** ** ** ** 02 00 03 00 ** ** ** ** SS SS SS SS PP 00 00 00 ** ** ** ** ** ** ** ** ** ** 20 00 01 00 ** ** ** ** ** **
            01 00 00 00 oo oo oo oo VV VV VV VV ** ** ** ** ss ss ss ss mm mm mm mm *7 ** ** ** ** ** ** **

こうやって、1Bずつずらしながら入る場所を探してった。4B境界におかないといけないなんて規則はないんだからねっ!

よく考えてみると

私の使ってるLinux箱はかなり過激な構成なんだよなあ…
うちでやると

kik@as305:~/work/codegolf/hello$ uname -a
Linux as305.localdomain 2.6.15.6 #1 PREEMPT Mon Mar 13 00:33:25 JST 2006 i686 pentium3 i386 GNU/Linux
kik@as305:~/work/codegolf/hello$ ./tiny-hello.bin 
Hello, world!

というわけで他所の環境で試してみた。

kik@debian:~$ uname -a
Linux debian 2.4.27-2-386 #1 Wed Aug 17 09:33:35 UTC 2005 i686 GNU/Linux
kik@debian:~$ ./tiny-hello.bin 
バスエラー

ちょw

a***e:~$ uname -a
Linux a***e 2.6.12.4 #1 SMP Mon Aug 15 03:19:29 JST 2005 i686 unknown
a***e:~$ ./tiny-hello.bin 
Segmentation fault
a***e:~$ 

ちょw

~$ uname -a
Linux ***** 2.6.11.12-xenU #2 Wed Jan 25 19:21:49 JST 2006 i686 GNU/Linux
~$ ./tiny-hello.bin
Segmentation fault
~$

ちょw

もしかして、うちでしか動かない?
カーネルのバージョン?それともディストロ?うちは

kik@as305:~/work/codegolf/hello$ cat /etc/lfs-release 
6.0

といういたって普通の環境なんだが…

どうも

mmapに失敗してるっぽい。
execがどのようにmmapするかというと、

  • p_offset をページ境界まで切り捨てる。
  • p_offset+p_filesz をページ境界まで切り上げる。
  • 上を含むページをp_vaddrをページ境界まで切り捨てて、そこにマップ

うちの環境だけp_fileszがでかくても実行に成功する。mmapの実装はfs依存だけど、ほとんどxfsなんだよなあ。不思議不思議。

mmap仮想メモリさえ確保できれば成功して、ページフォールトが起こるごとにファイル終端を超えてないかをチェックするっぽい。まあマップしてからトランケートとかもありうるから、それが正しいのだろう。ってことはファイル終端を越えたところにアクセスがあるかどうかが鍵だ。

http://www.linuxhq.com/kernel/v2.6/14/fs/binfmt_elf.c

これだ!bssがページ途中から開始してたら、そこからページ終端までをクリアしてる!
というわけで、ELF golferは2.6.14以降を使いましょう。