書籍紹介『Binary Hacks』

編集:ささだ

書籍紹介『Binary Hacks』

書名
Binary Hacks
サブタイトル
ハッカー秘伝のテクニック 100 選
著者
高林哲、鵜飼文敏、佐藤祐介、浜地慎一郎、首藤一幸
出版社
オライリー・ジャパン
定価
3,360 円 (税込)
ページ数
412 ページ
ISBN
4-87311-288-5

発売日 2006 年 11 月 11 日

版型
A5
書籍のページ
http://www.oreilly.co.jp/books/4873112885/
http://0xcc.net/binhacks/
目次
http://www.oreilly.co.jp/books/4873112885/toc.html

oreilly.co.jp – Online Catalog: Binary Hacks より引用:

本書のテーマは低レイヤのプログラミング技術です。低レイヤとは「生」のコンピュータに近いことを意味します。ソフトウェアの世界は抽象化の積み重ねによって進歩してきました。抽象化は低レイヤの複雑な部分を隠蔽し、より生産性、安全性の高い方法でプログラミングする手段を開発者に提供します。しかし、低レイヤの技術を完全に忘れてプログラミングできるかというと、そうもいきません。性能をとことん追求したい、信頼性をできるだけ高めたい、ときおり発生する「謎のエラー」を解決したい、といった場面では低いレイヤに降りていく必要に迫られます。残念ながら、抽象化は万全ではないためです。本書の目的は、そういった場面で使えるたくさんのノウハウ「Binary Hack」を紹介することです。本書では、Binary Hack を「ソフトウェアの低レイヤの技術 を駆使したプログラミングノウハウ」と定義し、基本的なツールの使い方から、セキュアプログラミング、OS やプロセッサの機能を利用した高度なテクニックまで広くカバーします。(「はじめに」より)

本書の紹介 (by ささだ)

はっきり言ってしまうと、本書はあんまり「バイナリ」って感じがしません。バイナリとか、バイナリアンとかいう言葉を聞くと、私は のような書籍を想像するんですが、先に引用した「はじめに」にもあるように、低レベルプログラミングについての技法の解説が主になっています。

ただし、低レベルプログラミングの本質的な解説というわけではなく、各プラットホーム固有の、低レベルプログラミングを行うための便利機能の紹介を行う書籍になっています。細かい内容はBinary Hacks の目次 を見てもらうとわかるかと思います。ライブラリの紹介やツールの使い方などがほとんどなので、マニュアルを読めばわかる内容ではありますし、「ふつう」のハッカーなら、ほとんど知っていてもおかしくないかも、とも思います。

ただ、私はまだまだ「ふつう」のハッカーの域に達していないので、全然知らない知識ばかりで、色々なツールなどの知識を得ることが出来てとても参考になりました。「そうそう、こんな機能が欲しかったんだよなー」という機能がいろいろ紹介されています。

本書は多分、バイナリアン育成のための書籍ではなく、バイナリアンが読んで喜ぶ書籍ではないかと思います。なので、自分がバイナリアンであるんではないか、と思う人は、一度手にとって読んでみるといいんじゃないかと思います。「これは便利そうだな〜」と、読んでみて思った人は、きっと他の記事も気に入るかと思います。

話は変わるのですが、ではバイナリアンになるための網羅的な、教科書的な書籍というのは存在するんでしょうか。「このご時勢、なんでバイナリなどと低レベルな層を触らなければならないのか」という疑問には、川合史朗さんが「本書に寄せて」で理由を書いているのですが、本書は「よし、これからは低レベルの層をもっと勉強するぞ!」と思った人がまず最初に読む本ではないと思います。「Hack#100 文献案内」を見てみると色々と書いてあるので、まずはそこを読んで修行してから、本書へ戻ってきて更に感動する、というのが理想系なんでしょうかね。

バイナリアンが経験しているであろう低レベルプログラミングが持つ「ドキドキ感」は、書籍で学ぶものでもないのかもしれませんので、そのような書籍はありえないのかもしれません。ただ、本書を読んで、なんだかよくわからないけど「ドキドキ感」を感じるという人は、すでにバイナリアンなのかもしれません。

実際に使ってみた事例

言葉を繕ってもあまり意味がない、というか、ありそうな紹介が書けそうに無いので、自分が開発している YARV に、本書によって得た知識を実際に利用してみた、という事例をご紹介します。

お題は「Hack#63 C でバックトレースを表示する」です。ここでは、glibc が持つ backtrace() 関数を利用して、C 関数のバックトレースを表示する方法を紹介しています。

この機能を積極的に使って、Ruby の例外処理をこの機能を利用して実現することも考えられますが (プログラムカウンタ <-> 例外処理情報の対応表を先に作る)、glibc 環境でないと使えない技、もしくはマシン語命令を用いた関数フレームの解析を行わないといけないので、Ruby の「なるべく処理系は環境非依存に作る」という原則から反してしまうので、そこまではしませんでした。

実際につけた機能は、処理系に何かしらのバグが発生したとき (具体的には SEGV シグナルハンドラを受け取ったとき)、終了時にこの機能を用いて C のバックトレースをアドレスで表示する機能を付けました。backtrace 関数を利用できる環境でのみ、この機能が有効になります。

実際のコードは次のようになっています。

#if HAVE_BACKTRACE
#include <execinfo.h>
#define MAX_NATIVE_TRACE 1024
    {
	static void *trace[MAX_NATIVE_TRACE];
	int n = backtrace(trace, MAX_NATIVE_TRACE);
	int i;

	fprintf(stderr, "-- backtrace of native function call (Use addr2line) --\n");
	for (i=0; i<n; i++) {
	    fprintf(stderr, "%p\n", trace[i]);
	}
	fprintf(stderr, "-------------------------------------------------------\n");
    }
#endif

処理系にバグがあると、次のような出力を表示します。

-- stack frame ------------
0000 (0x2aaaaacd7010): 00000004
0001 (0x2aaaaacd7018): 00000005
0002 (0x2aaaaacd7020): 00000004
0003 (0x2aaaaacd7028): 00000001
0004 (0x2aaaaacd7030): 2aaaaac202c0
0005 (0x2aaaaacd7038): 00000004
0006 (0x2aaaaacd7040): 00000001 <- lfp <- dfp
-- control frame ----------
c:0004 p:---- s:0007 b:0007 l:000006 d:000006 CFUNC  :SDR
c:0003 p:0007 s:0004 b:0004 l:000003 d:000003 TOP    ../trunk/test.rb:1
c:0002 p:---- s:0002 b:0002 l:000001 d:000001 FINISH
c:0001 p:---- s:0000 b:-001 l:000000 d:000000 ------
---------------------------
DBG> : "../trunk/test.rb:1:in `<main>'"
-- backtrace of native function call (Use addr2line) --
0x4949cf
0x4955e9
0x490a0c
0x492b1d
0x4956cd
0x414713
0x414755
0x4184bd
0x411f63
0x3f8d21c784
0x411e99
-------------------------------------------------------

アドレスの列が出力されるため、addr2line コマンドを利用してソース上の場所を特定することが出来ます。普段は gdb 経由で実行するしか取れなかった C の関数呼び出しのバックトレース情報が、処理系のエラー時に必ず出力されるようになったので、今後はバグの解析が楽になるのではないかと期待しています。

この記事について

ところで、書籍紹介の記事は、いつもなら Ruby 関連書籍が出たときに、出版社、執筆者の方に「載せませんか?/載せる内容ください」とお伺いをたてるだけという、こちらはほとんど何もしないで楽に記事が一本増えてラッキーと思う記事なのですが (いや、冗談ですよ)、執筆者の一人の方に本をあげるからるびまで紹介しろ、と、もとい紹介してくださいませんか、と言われたのでささだが筆を取った次第です。

えーと、いい本だと思いますのでぜひお買い求めください。はい。