オライリー矢野様より献本御礼。

この本が、あなたの仕事に直接役に立つかと言えば、あなたが Linux Kernel Hacker でない限り、役に立たない。「役に立つ」視点から見た場合の本書の想定読者の範囲は、恐ろしいほど狭い。間違っても、「メールアドレスにマッチする正規表現のバグ」を見つけるのに本書を役立てようとしてはならない。

しかし、狭いだけに、深い。そしてその深さを覗き見ることは、本書が全く役に立たない読者にも大いに意味があることだと考える。イチローのように打てなくても、羽生のように指せなくても、彼らが何を目指し、そのために何をしているのかを知ることに何らかの意味があるのと似て。

本書「DEBUG HACKS」は、「狭く深い」のが特長のHacksシリーズの中でも、最も狭く、そして深い一冊。

2009-04-07 - 未来のいつか/hyoshiokの日記
オライリーのページから目次を見ていただければわかるが、アプリケーションからカーネルのデバッグまで幅広く、記述している。

そういう共著者の言葉とは裏腹に、その度合いは「Binary Hacks」の比ではない。

目次 - Book:Debug Hacksより
推薦の言葉
クレジット
はじめに
1章 こころがまえ(warmingup)
1. デバッグとは
2. Debug Hacksマップ
3. デバッグの心得
2章 デバッグ前に知っておくべきこと
4. プロセスのコアダンプを採取する
5. デバッガ(GDB)の基本的な使い方(その1)
6. デバッガ(GDB)の基本的な使い方(その2)
7. デバッガ(GDB)の基本的な使い方(その3)
8. Intelアーキテクチャの基本
9. デバッグに必要なスタックの基礎知識
10. 関数コール時の引数の渡され方(x86_64編)
11. 関数コール時の引数の渡され方(i386編)
12. 関数コール時の引数の渡され方(C++編)
13. アセンブリ言語の勉強法
14. アセンブリ言語からソースコードの対応を調べる
3章 カーネルデバッグの準備
15. Oopsメッセージの読み方
16. minicomでシリアルコンソール接続を行う
17. ネットワーク経由でカーネルメッセージを取得する
18. SysRqキーによるデバッグ方法
19. diskdumpを使ってカーネルクラッシュダンプを採取する
20. Kdumpを使ってカーネルクラッシュダンプを採取する
21. crashコマンドの使い方
22. IPMI watchdog timerにより、フリーズ時にクラッシュダンプを取得する
23. NMI watchdogにより、フリーズ時に
クラッシュダンプを取得する
24. カーネル特有のアセンブリ命令(その1)
25. カーネル特有のアセンブリ命令(その2)
4章 実践アプリケーションデバッグ
26. SIGSEGVでアプリケーションが異常終了した
27. バックトレースが正しく表示されない
28. 配列の不正アクセスによるメモリ内容の破壊
29. ウォッチポイントを活用した不正メモリアクセスの検知
30. malloc()やfree()で障害が発生
31. アプリケーションのストール(デッドロック編)
32. アプリケーションのストール(無限ループ編)
5章 実践カーネルデバッグ
33. カーネルパニック(NULLポインタ参照編)
34. カーネルパニック(リスト破壊編)
35. カーネルパニック(レースコンディション編)
36. カーネルのストール(無限ループ編)
37. カーネルのストール(スピンロック編その1)
38. カーネルのストール(スピンロック編その2)
39. カーネルのストール(セマフォ編)
40. リアルタイムプロセスのストール
41. 動作がスローダウンする不具合
42. CPU負荷が高くなる不具合
6章 差がつくデバッグテクニック
43. straceを使って、不具合原因の手がかりを見つける
44. objdumpの便利なオプション
45. Valgrindの使い方(基本編)
46. Valgrindの使い方(実践編)
47. kprobesを使って、カーネル内部の情報を取得する
48. jprobesを使って、カーネル内部の情報を取得する
49. kprobesを使って、カーネル内部の任意箇所の情報を取得する
50. kprobesを使って、カーネル内部の任意箇所で変数名を指定して情報を取得する
51. KAHOを使い、コンパイラによってOptimized outされた変数の値を取得する
52. systemtapを使って動作中のカーネルをデバッグする(その1)
53. systemtapを使って動作中のカーネルをデバッグする(その2)
54. /proc/meminfoでわかること
55. /proc//memでプロセスのメモリ内容を高速に読み出す
56. OOM Killerの動作と仕組み
57. フォルト・インジェクション
58. フォルト・インジェクションを利用したLinuxカーネルの潜在的なバグの発見
59. Linuxカーネルのinitセクション
60. 性能の問題を解決する
61. VMware Vprobeを使用して情報を取得する
62. Xenでメモリダンプを取得する
63. GOT/PLTを経由した関数コールの仕組みを理解する
64. initramfsイメージをデバッグ
65. RT Watchdogを使ってリアルタイムプロセスのストールを検知する
66. 手元のx86マシンが64ビットモード対応かどうかを調べる
付録 Debug Hacks用語の基礎知識
索引

なにしろ Linux / i386 限定だ(Hack #66はとにかく)。しかも目次を見てのとおり、カーネル関連が Hack の過半を占める。 i386 で Linux というのは確かにサーバー用途では最もメジャーであるが、それでもほとんどの関係者はユーザーではあってもハッカーではない。仮に問題を見つけても、バグフィックスを祈って待つのが関の山だし、実際本書の著者たちのような達人たちがあっという魔に直してくれる。なぜあなたがそれを知る必要があるのか。

確かに、必要、ない。もしあなたがユーザーに留まるのであれば。

しかし、もし単なるユーザーであることを超えて、何らかのハッカーになることを志すのであれば、やはり一番よいのは、たとえ分野が異なっていても、トッププログラマーの仕事の進めぶりに触れてみるのが一番だ。達人というのは、ただ「ある」だけで、まわりの人々の心をハックしてしまうのだから。

本書はまさしくそういう本だ。本書を見れば、なぜ彼らの仕事において printf デバッグが役に立たないのかがわかる。printf を挟むという行為そのものが、プログラムの挙動そのものを変えてしまいかねないし、また実際に変えてしまうのだ。

特にそれが強く感じられるのが、第5章。そこでは本当に存在したカーネルバグを、本当に退治している様子が克明に記録されている。本書には、本書のために「作りおろされた」例題が実に少ない。社交辞令抜きで、本書は本当のバグを、本当にデバッグするかが書かれているのだ。

それだけに、本書の「惜しくも役に立たないHack」の多いこと。私は Linux よりも FreeBSD を使う機会が多いのだが、ユーザーランドではさほど違わない、unameでもしてみなければどちらを使っているのかわからないほど似たOSが、本書のレベルではこれほど違うのかということにかなり悔しいと同時に嬉しい思いをした。例えば私はFreeBSD::i386::Ptraceというものを作ったが、Linuxの知見は、Ptraceという名前以外ほとんど役に立たなかった。ぐぐっても答えは全く出てこない。man pageなんぞ何も書いていないに等しい。結局カーネルのソースコードを読み、GDBのソースコードを読み、それでもわからないところは実際に試してやるしかなかった。「似たような道」ではあるが、同じ道ではない以上、同じようには出来ない。そうやって薮をかき分けて道を造るのは実に楽しい作業ではあったが、本書のような道しるべがあればもっと楽が出来たということは確かだ。しかし前述のとおり、それは「本書のような」であって本書ではない。そこが難しいところだ。

その意味で、本書は実に使いどころが難しい一冊であり、むしろ無理に「使おう」としない方がいい一冊であるように感じられた。私に「本書の想定ユーザーからわずかに、しかし決定的にずれている」ことによるバイアスがあることは認めるが、それを差し引いてもなお本書の狭さと深さは Hacks シリーズの中で際立っていることは明らかだ。内容もさることながら、行間をどれだけ読めるか。私を含むLinux Kernel ハッカーならざる読者も、それであれば大いに学ぶことができそうだ。

Dan the Occasional Linux User