狠狠撸

狠狠撸Share a Scribd company logo
セキュリティ&プログラミングキャンプ 2009 ソースコードの読み方 よしおかひろたか 2009 年 8 月 13 日
講師紹介 よしおかひろたか、 Debug Hacks 著者、カーネル読書会主宰、 YLUG( 横浜 Linux Users Group) 、勉強会勉強会 未来のいつか /hyoshio の日記 http://d.hatena.ne.jp/hyoshiok ユメのチカラ http://blog.miraclelinux.com/yume/ [email_address] http://twitter.com/hyoshiok
お題 ソースコードの読み方
ソースコードの読み方 ソースコードって何? 人間がプログラミング言語などを用いて記述したもの。 そのままではコンピュータは実行できないので、通常、コンパイラと呼ばれるソフトウェアで直接実行できる形式に変换して実行されるか、インタプリタと呼ばれるソフトウェアで字面を解釈し実行される。
トラブルシューティングと ソースコードの読み方 トラブルシューティングと問題の理解 実践的なコードの理解
ソースコードを読むチカラ プログラマの基礎体力 ソフトウェア開発コストの大部分は保守 不具合修正、改良、機能追加にはコードの理解が必須 技術者の付加価値 OSSは深追いできる 陳腐化しにくい プロフェッショナルとしての研鑚 すぐれた技術者はソースコードを上手に読む
コードの読み方 なぜ、コードを読むのか どのように、読むのか
なぜコードを読むのか? 仕事だから(目的中心) トラブルシューティング(不具合修正) 機能修正、機能開発 自己研鑚、勉強 趣味だから(興味中心) 楽しいから 自己啓発(知的好奇心) 不純な動機 形から入る
なぜコードを読むのか 目的中心の場合 対象に対する基礎知識は必要 アーキテクチャ OS、プログラミング言語、RDBMS、… 定番の教科書で知識を得る
なぜコードを読むのか 興味中心の場合 人それぞれ、人生いろいろ 無目的でもいいじゃないか 熟読、濫読、積読、黙読、音読、再読、誤読、精読、速読、耽読、通読、復読、輪読、朗読、輪読、…
コードの理解について モットー: コードは読むな、 理解しろ?
どのようにコードを理解するのか 個人的な方法を紹介する 唯一あるいはベストな方法というわけでもない 適材適所、もっと良い方法があると思う 公開することによって進化したい(もっと良い方法への模索)
ソースコードを読む视点
理解の仕方、読み方 静的、動的理解 微視的、巨視的 規模の把握 ツールの利用 事例
静的理解、動的理解 静的理解 字面での理解 動的理解 動作による理解
静的、動的構造 静的構造(デモ) 規模 ディレクトリ構造 名前つけ規約 動的構造 呼び出し経路 プロファイリング 実行結果
微視的、巨視的 微視的:細部からの理解 最終的にはコードの一行 巨視的:全体からの理解 規模、構造、機能など。実行結果(性能?) 俯瞰図、鳥瞰図。
規模の把握(巨視的理解) 規模重要 規模(相手)を知らずして作戦を立てられない 大局的な地図、俯瞰図、鳥瞰図 大規模になればなるほど、システマティックな方法論が必要になってくる 巨視的な理解
規模の把握 小規模: 100K 行未満程度、 ファイル数 100 未満 10 人未満 中規模: 100K 行? 1M 行程度 ファイル数 100 ? 1000 未満 100 人未満 大規模: 1M 行以上 ファイル数 1000 以上 100 人以上 ざっくりの規模感
規模の把握(例) find -type f -name "*.[ch]"|wc find -type f -name "*.[ch]"|xargs wc|grep total
ディレクトリ構造 トップディレクトリは、ソフトウェアの論理的構造を表している doc ドキュメント lib ライブラリ関係 test テスト ソースツリーの把握
ドキュメント README, INSTALL, COPYING, … 内部ドキュメント(Docs) リリースノート ChangeLog
変更の履歴 ChangeLog/Release Notes コード管理システム 例:Linux git/Subversion/CVS Mailing List Wiki blog 変更(時間軸)の微視的理解
ドキュメント、情報収集 マニュアルを読む サーチエンジン(Google)に聞く Mailing List Bug database 開発者との会話(シンポジウムなど) 勉強会
ソースコードを読む视点
いよいよコードを読む? ツール エディタ:emacs デバッガ:gdb クロスレファレンス:cscope カーネルの場合、クラッシュダンプ(crash)
デモ、実習 例題としてrubyを読むことにする。 GNU Hello http://savannah.gnu.org/projects/hello
実習 ソースコードの規模を理解する ディレクトリ構造を理解する ビルドする ソースコードのナビゲート 機能変更をする
実習 ディレクトリ構造を理解する ファイル名を眺める ファイル数を調べる プログラムの行数を調べる
実習 ソースコードの入手 $ git-clone git:// ( 講師に聞いてください ) ビルドの準備 README をよく読む 必要なツールを揃える - automake < http://www.gnu.org/software/automake/ > - autoconf < http://www.gnu.org/software/autoconf/ > - bison < http://www.gnu.org/software/bison/ > - gettext < http://www.gnu.org/software/gettext/ > - git < http://git.or.cz/ > - gperf < http://www.gnu.org/software/gperf/ > - gzip < http://www.gnu.org/software/gzip/ > - perl < http://www.cpan.org/ > - rsync < http://samba.anu.edu.au/rsync/ > - tar < http://www.gnu.org/software/tar/ >
実習 ビルド $ time git clone ssh:// ( 講師から情報を得る ) $ cd ruby $ time autoconf $ time ./configure $ time make $ time make test
$ git checkout -b trunk origin/trunk $ autoconf ./configure make -j4 miniruby
動的理解 ビルド
動的理解 ともかく動かす make strace ltrace gdb oprofile リグレッションテスト ベンチマークテスト
make とりあえず、make 実行環境の構築 gcc -g (デバッグシンボルを付加する) 通常はMakefileのCFLAGSなどに設定 cscopeのインデックスを作成 ビルドはemacsのshellなどから行い、ビルドのログを取得しておくと便利
strace システムコールのトレース $ strace ruby -v execve(&quot;/usr/local/bin/ruby&quot;, [&quot;ruby&quot;, &quot;-v&quot;], [/* 39 vars */]) = 0 uname({sys=&quot;Linux&quot;, node=&quot;asianux2.miraclelinux.com&quot;, ...}) = 0 brk(0)  = 0x976a000 access(&quot;/etc/ld.so.preload&quot;, R_OK)  = -1 ENOENT (No such file or directory) open(&quot;/etc/ld.so.cache&quot;, O_RDONLY)  = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=89946, ...}) = 0 old_mmap(NULL, 89946, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fea000 close(3)  = 0 open(&quot;/lib/libdl.so.2&quot;, O_RDONLY)  = 3
gdb デバッガはコードを理解するためにある ∴コードを読むために使う http://savannah.gnu.org/projects/gdb
gdbで読むための準備 gcc -g でコンパイル コンパイルしたコードサイズが大きくなる以外、特に副作用はない printfデバッグは有害無益
gdb ブレークポイントを設定 ウオッチポイント(変数の変更) run 止まった時点で bt  スタックフレームの表示 p  変数の表示 c  実行再開、 s  ステップ実行(関数に潜る)、 n  ステップ実行(関数に潜らない) 繰り返す
oprofile プロファイラー 実行時のボトルネックを発見 # opcontrol --start テストの実行 # opcontrol --stop # opreport -l http://oprofile.sourceforge.net/news/
oprofile CPU: Core Solo / Duo, speed 2666.77 MHz (estimated) Counted DCACHE_PEND_MISS events (Weighted cycles of L1 miss outstanding) with  a unit mask of 0x00 (Weighted cycles) count 100000  vma  samples  %  linenr info  app name symbol name 000000000042be50 244787  33.2383  gc.c:1661  ruby  os_each_obj 000000000042bfac 1  4.1e-04  gc.c:1599 000000000042bfb9 5  0.0020  gc.c:1599 000000000042bfbe 6  0.0025  gc.c:1599 000000000042bfd0 4862  1.9862  gc.c:1601 000000000042bfd3 228573  93.3763  gc.c:1601 000000000042bfd6 2698  1.1022  gc.c:1601 000000000042bfd8 250  0.1021  ruby.h:672
oprofile 高速道路で、ズバリ最もコストのかかっているところに連れて行ってくれる コードを読まないで、理解する極意
微視的理解 ひたすらコードを読む 王道はない ↑身もふたもない データ構造、変数などに注目し、どこで定義され、参照され、代入(変更)されているかという観点でみる デバッガとエディタ、クロスリファレンスツールを駆使
微視的理解 $ time find -type f -name '*.[ch]' -or -name '*.cpp'  -or -name '*.cxx' | xargs egrep -l hogehoge $ time grep -r –include='*.[ch]' hogehoge .  hogehoge を含むファイルを検索
微視的理解 クロスリファレンスツール 変数の定義(型情報)、変更(代入)、参照 変数(関数)が、どのように定義されていて、どのように参照、変更されているかを追う cscope http://cscope.sourceforge.net/ lxr http://lxr.linux.no/ GNU GLOBAL http://www.gnu.org/software/global/ ack-grep
実習 cscopeを利用する $ time cscope-indexer -r emacs を利用する gdb を利用する oprofile を利用する
ソースコードを読む视点
参考書 Linux 詳解LINUXカーネル第三版 ISBN:487311313X Linuxカーネル2.6解読室 ISBN:4797338261 コードリーディング ISBN:4839912653 Ruby ソースコード完全解説 ISBN:4844317210(品切れ中) http://i.loveruby.net/ja/rhg/
ユメのチカラ(ブログ) http://blog.miraclelinux.com/yume/ ブックマークで見た人気エントリー ソースコードの読み方(524個) http://blog.miraclelinux.com/yume/2007/08/post_d6bd.html デバッグ方法論(99個) http://blog.miraclelinux.com/yume/2007/08/post_d3eb.html 多くの人に興味がある話題
ブログ:ユメのチカラ http://blog.miraclelinux.com/yume/ 未来のいつか /hyoshiok の日記 http://d.hatena.ne.jp/hyoshiok/

More Related Content

Programming camp Codereading