【追記】さらにその後,「『7f454c46 01010100 00000000 00000000』の時 点でelfファイルであることは判るが,Linuxで作られたかは0x0114バイトは 見ないと判らないはず,この人は『バイナリ萌え』ではない!」との突っ込 みを頂きました.
0xcafebabe の話を知った大学生の頃,危うくバイナリ萌えの暗黒面に落ち そうになったものの,軽うじて生還して今は普通人として暮らしています.
というわけでバイナリ萌えでない私にとっては,上の「Linuxで作られたか は0x0114バイトは見ないと判らない」はすごく不思議だった.だって ELF って 8 バイト目に OS/ABI あるじゃん.で,ELFOSABI_LINUX (= 0x03) っ て定義されてるじゃん.そこ見ればいいんじゃないの?
…と思って手近にあった Vine Linux に転がっているバイナリを調べてみる と,8 バイト目は軒並 0x00 なのであった.0x00 は ELFOSABI_NONE であり ELFOSABI_SYSV である.で,確かに readelf すると
% readelf -a /bin/ls | grep OS/ABI OS/ABI: UNIX - System V
と表示されるのであった.むー.
さてそれではどうやって Linux のものだと判定すればよいのか,そしてそ れはなぜ「0x0114バイトは見ないと判らない」のか,ちょっと調べてみるこ とにした.
調べたのは file コマンド.
% file /bin/ls /bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1, for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
てな感じで Linux だと判定してくれるので,きっと何か手がかりがあるだ ろう.
というわけで FreeBSD の /usr/src/contrib/file/readelf.c あたりを 眺めてみると,donote() の中で判定しているようだ.ELF のプログラムヘッ ダのうち NOTE タイプのものを探して,その先頭 Elf32_Nhdr サイズ分 (た だし 32 ビット ELF の場合.定義は file/readelf.h の中で,実際のサイ ズは 12 バイト) スキップしたところに 'G', 'N', 'U', '\0' という 4 バ イトがあることを確認し,その次の 1 バイトを調べている.そこが 0x00 だったら GNU/Linux であるという判定をしているようだ.ちなみにそこに 出てくる値としては
#define GNU_OS_LINUX 0 #define GNU_OS_HURD 1 #define GNU_OS_SOLARIS 2
が定義されている.ちょwww HURD って単語久々にみたわwwwwwwwww
NOTE タイプのプログラムヘッダがどこにあるかというと,
% readelf -a /bin/ls (略) Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align (略) NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4 (略)
てな感じになっていて,先頭からのオフセット 0x108 バイトのところから 始まるらしい.ここから Elf32_Nhdr 分の 12 バイト進んだ 0x114 の,さ らに 'G', 'N', 'U', '\0' の分の 4 バイト進んだところ,つまりオフセッ ト 0x118 バイトのところを見るとようやく Linux かどうかがわかる,とい う仕組みのようだ.実際に見てみると,
% hexdump -c /bin/ls | grep ^0000110 0000110 001 \0 \0 \0 G N U \0 \0 \0 \0 \0 002 \0 \0 \0
となる.うーん,なるほど.
ついでに書いとくと,NOTE タイプのプログラムヘッダは必ずしも 0x108 か ら始まるわけじゃなくて,例えば /bin/rpm なんかは
NOTE 0x000094 0x08048094 0x08048094 0x00020 0x00020 R 0x4
なのであった.つまりオフセット 0xa4 (= 0x94 + 12 + 4) を見る必要があ るってことでいいかな?
% hexdump -c /bin/rpm | grep ^00000a0 00000a0 G N U \0 \0 \0 \0 \0 002 \0 \0 \0 002 \0 \0 \0
よさげである.
というわけで,どうやら「Linuxで作られたかは0x0114バイトは見ないと判 らないはず,この人は『バイナリ萌え』ではない!」という突っ込みもバイ ナリ萌えとしてはまだツメが甘いようです.うーむ,バイナリアン恐るべし. ついて行けん.
で,最初の話に戻るんですが,これらのファイルってどうして OS/ABI に ELFOSABI_LINUX を使わないんでしょう? 逆に言うと ELFOSABI_LINUX って どういうときに使われてるんでしょう? 教えて偉い人.
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12
2002 : 01 02 03 04 05 06 07 08 09 10 11 12
2001 : 01 02 03 04 05 06 07 08 09 10 11 12
2000 : 01 02 03 04 05 06 07 08 09 10 11 12
1999 : 01 02 03 04 05 06 07 08 09 10 11 12
1998 : 01 02 03 04 05 06 07 08 09 10 11 12
1997 : 01 02 03 04 05 06 07 08 09 10 11 12
1996 : 01 02 03 04 05 06 07 08 09 10 11 12
最終更新時間: 2008-04-23 08:31
* [baby touch] 『あまり使われないのは、システムコールとかの"実装"に依存し... (2007-11-06 21:15:48)