2015年9月6日日曜日

バイナリファイルの可視化(ARMの機械語コードの縦縞が見たい!)

0. 要旨

「ARMの機械語コードをビットマップ表示のできるバイナリエディタで開いてみると、縦に線が見える」という噂がある。
しかし、hexeditにはそんな機能はない。そうだ、機械語コードにちょいっとヘッダをつけて、PNMファイルにしてしまおう。


1. ARMの機械語

最近、「熱血!アセンブラ入門」という本を読んでいる。
熱血!アセンブラ入門 サポートページからファイル一式も手に入れて、環境もばっちり整えて、ひたすらコード(ソースコードとアセンブリコードと機械語コード)で遊んでいるのだ。
そんな中でARMの機械語コードの縦線の話があるなら、やるしかない。

以下、登場する機械語コードは上記の熱血!アセンブラ入門 サポートページ
「環境構築の方法」で配布されている配布物を、うちでコンパイルしたものである。

2. PNM形式

PNM形式は画像形式の一種であって、4行(白黒なら3行)のヘッダの後に、ASCIIの数字、またはバイナリの数値を羅列した形式である。
(ASCII、バイナリ)と(白黒、グレイ、カラー)の直積で6種類があり、それぞれP1からP6のマジックナンバーが与えられている。wikipediaPNM画像の作成をご覧いただきたい。

単純な形式なので「そのバイトの値」を目で見るにはもってこいだ。
今回は、バイナリ、白黒のP4にする。

P4のファイル形式は、次のようになっている。
1行め:P4と書く
2行め:#と書く
3行め:横と縦のサイズを空白で区切って書く
4行め:ビット列が続く(0は白、1は黒で左上から右に順番に絵の色を指定していると解釈される)
拡張子は、P4だと白黒だから、pbmになる。

3. 画像にしよう

では、早速やってみよう。
サンプルコードをARM向けにコンパイルした実効形式のファイルがarm-elf.xである。

wc -c arm-elf.x|awk '{printf "P4\n#\n128 %d\n",$1/16}'>arm-elf.pbm ; cat arm-elf.x >> arm-elf.pbm

(コードは改行されているように見えるけれど、もちろん一行で。)
横のサイズを128にしたのは、hexeditを80x24のターミナルで開くと、1行を16byte=128bitで表示されるからである。

意図したとおりのヘッダがついたか確認してみよう。
$ less arm-elf.pbm
P4
#
128 877
^?ELF^A^A^Aa^@.....
よしできているようだ。

では画像として開こう。

4. 画像を見よう

eogでもemacsでもgimpでもdisplayでもpbmは認識される。
(ただし、displayとemacsではズームインの仕方がわからなった
emacsの虫眼鏡をクリックしたら、[I-search:]ですって)。
なお、eogはanti-aliasingがかかることがある。
Edit->Preferenceで Smooth image when zoomed-inのチェックを外しておこう。

全体像を次に示す(ブログにアップするために、pbmをpngにeogで変換した)。



左上で0と1との対応を確認しよう。
コードの最初の部分をhexeditと絵で次に示す。


arm-elf.xの始まりは
7F 45 4C 46 ...
だから
0111 1111 0100 0101  ...
だから
白黒黒黒 黒黒黒黒 白黒白白 白黒白黒 ...
と正しくなっているようだ。

機械語コードの部分をhexeditと絵を次に示す。
機械語部分は、0x1400バイトめ(320行め=0x1400/0x4、1行4バイトだから)から始まるので、そのあたりにズームインした。



よし。縦縞が見えた。

5. グレイスケールでも見てみよう

PNMのP4はグレイスケールの画像形式である。ここでは8ビットで1ピクセルを表すようにしてみよう。

wc -c arm-elf.x |awk '{printf "P4\n#\n16 %d\n",$1/16/8\n255}'>arm-elf.pgm ; cat arm-elf.x >> arm-elf.pgm

機械語コード部分を示す。


よし。縦縞だ。

6. まとめ

機械語コードは、catとawkで画像化できて、viewerで絵として見られる。

以上
(2016年12月10日、誤字修正)