Your SlideShare is downloading. ×
0
Dtrace in NetBSD読んでいる・・・
(まだまだ途中・・・Ver1.1)
@akachochin
使用上の注意
●
このスライドはNetBSDのdtraceのソースを読ん
だ*途中経過*をまとめたものです。よって、資
料を書いている私も完璧に理解していません>
<
●
このスライドは今年の「カーネル/VM探検隊」
で飛び入りLTで使ったスラ...
自己紹介
●
普段は仕事でNetBSDをMFPやプリンタに組み
込んでます。
●
今まではMIPSに操を立ててたけど、最近は
色々あります(笑)
●
趣味は赤提灯めぐり。場末の飲み屋さいこー。
●
Twitterは@akachochinです。皆...
dtraceって何だ?
●
今は亡きSunがSolarisに組み込んだ動的トレー
スツール(言語)。
●
DTrace を使用することにより、システム、ア
プリケーションに手を加えることなく、動的な
トレースをとることができる。
●
NetBS...
もうちょい詳しく!その1~用語~
●
dtrace では、OSとユーザープロセスに動的に変
更を加え、「プローブ」と呼ばれる計測ポイン
トを仕込むことができる。要はプローブを実行
することでdtrace側の処理を実行し、必要な記
録をとることが...
もうちょい詳しく!その2
システムでサポートしているプロバイダとプ
ローブの組はdtrace -lで表示できるよ。こんな
感じ。
● # dtrace -l | head -n 10
● ID PROVIDER MODULE FUNCTION
...
もうちょい詳しく!その3
プロセスごとのwriteシステムコールにかかる平均時間を求める
fbt:netbsd:sys_write:entry
{
self->ts = timestamp;
}
fbt:netbsd:sys_write:ret...
もうちょい詳しく!その4
●
先の実装例はプロセスごとのsys_write()にかか
る平均時間を求めるものです。
●
ということは、sys_write()の先頭とreturnの箇所
で何らかの方法でdtrace処理が呼び出されない
といけない...
ここで疑問
●
プロバイダたるカーネルモジュールが動的に
「プローブ」を有効にすることはわかった。
●
しかし、「動的に有効」ってどうやってやって
いるの?
●
実際、例に出てきたsys_write()読んでも怪しげ
なマクロなどのプローブらし...
ソースを探検する前に
●
dtrace -lの結果から、システムコールに対応し
ているプロバイダ(カーネルモジュール)はfbtの
ようだ。
●
超絶はしょりまくりでネタバレすると、dtrace
のハンドリング(ロギング処理)をしているのは
dt...
ソースを探検!その1
●
dtrace_probe()はfbt_invop()から呼ばれており、
この関数はdtrace_invop_add()の引数で渡されて
いるものである。このパターンは多分関数ポイ
ンタの登録...?
●
dtrace_...
ソースを探検!その2
●
i386側の実装を見ることにする。
dtrace_invop_add()にはdtrace_invop_hdlrというハ
ンドラ構造体がある。ここにfbt_invop()が登録
される。
●
別のソースに実装されているd...
ソースを探検!その3
●
dtrace_invop()は、dtraceカーネルモジュールの
アセンブラ関数でdtrace_invop_startと言う関数
から呼ばれている。
●
dtrace_invop_startのアドレスはdtraceの初...
ソースを探検!その4
●
で、突き詰めていくと、dtrace_invop_jump_addr
という関数ポインタに行き着く。
●
dtrace_invop_jump_addrはどこにあるのか?
dtraceモジュールの中で呼んでいる箇所はな
い...
ソースを探検!その5
●
ここまでをまとめると・・・
trap6の例外ベクタ --> dtrace_invop_jump_addr経
由でdtrace_invop_startをコール -->
dtrace_invop_startから dtrac...
閑話休題、trap6とは?
●
Intel® 64 and IA-32 Architectures Software
Developer’s Manual 1846ページによると・・・
「Interrupt 6—Invalid Opcode E...
ソースを探検!その6
●
ここまでのところで、どうやら「不正命令」を
実行させることでtrap6を発動し、その勢いで
dtraceの処理を呼び出すことがわかってきた。
●
でも、ビルド時にはない「不正命令」を各カー
ネル関数にどうやって埋め込む...
ソースを探検!その7
●
これまた細かい途中経過をすっ飛ばすと、fbt
カーネルモジュールのfbt_enable()という関数で
プルーブを有効にしている。
●
その中に↓なコードがあるよん。
● for (; fbt != NULL; fbt...
ソースを探検!その8
●
前後の処理ではWrite Protectionを外
し、patchpointなるアドレスの指す箇所に
patchvalという値を書き込んでいる。
●
何となく、patchvalが「不正命令」でそれを
patchpoin...
ソースを探検!その9
●
fbtp_patchpointおよびfbtp_patchvalは
fbt_provide_module_cb()という関数で設定され
ている。
●
この中では渡ってきたアドレスとサイズを使っ
て命令の解析をしているよう...
ソースを探検!その10
●
なるほど。与えられた関数のアドレスとそのサ
イズを使ってそこにある命令を解析しつつ、関
数の先頭と末尾を特定するのはわかりました。
●
そして、FBT_PATCHVALで定義される未定義
命令をpatchvalに、関...
ソースを探検!その11
●
では、関数のアドレスとそのサイズはどこから
取得しているの?
●
先にお話ししたfbt_provide_module_cb()は
ksyms_mod_foreach()経由で呼ばれている。
●
ksyms_mod_f...
ソースを探検!その12
●
シンボルやそのサイズはどこにあるの?
●
細かい事をはしょると、ELFの.symtabセクショ
ンに存在する。
●
データフォーマットを知りたい?それなら
http://www.skyfree.org/linux/r...
というわけで強引にまとめ
●
dtraceのトレース関数はtrap6経由で呼ばれる。
●
カーネルやカーネルモジュールの.symtabセク
ションの情報を使って、関数のシンボルを獲得
している。
●
シンボル情報(アドレス、サイズ)を使って、そ...
かなりはしょりまくりで乱暴でした
が
●
ご清聴ありがとうございましたm(_ _)m
Upcoming SlideShare
Loading in...5
×

NetBSD BOFで話したDTraceの話

273

Published on

NetBSD BOF 2013(http://www.jp.netbsd.org/ja/JP/JNUG/event/20130713BOF/)でお話ししたときのスライド

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
273
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "NetBSD BOFで話したDTraceの話"

  1. 1. Dtrace in NetBSD読んでいる・・・ (まだまだ途中・・・Ver1.1) @akachochin
  2. 2. 使用上の注意 ● このスライドはNetBSDのdtraceのソースを読ん だ*途中経過*をまとめたものです。よって、資 料を書いている私も完璧に理解していません> < ● このスライドは今年の「カーネル/VM探検隊」 で飛び入りLTで使ったスライドです。(しかも ほとんど直してない・・・!)よってかなりは しょりまくっています。 ● よくわからないところはソースを読みましょ う。きっと面白いですよ・・・・。
  3. 3. 自己紹介 ● 普段は仕事でNetBSDをMFPやプリンタに組み 込んでます。 ● 今まではMIPSに操を立ててたけど、最近は 色々あります(笑) ● 趣味は赤提灯めぐり。場末の飲み屋さいこー。 ● Twitterは@akachochinです。皆様フォローを(笑) でも、たまに酔いどれてつぶやきます。ご勘 弁。
  4. 4. dtraceって何だ? ● 今は亡きSunがSolarisに組み込んだ動的トレー スツール(言語)。 ● DTrace を使用することにより、システム、ア プリケーションに手を加えることなく、動的な トレースをとることができる。 ● NetBSD6.0からx86限定だけど、dtraceがサポー トされた。 ● FreeBSDやMac OS Xでもサポートされているら しいぞ。
  5. 5. もうちょい詳しく!その1~用語~ ● dtrace では、OSとユーザープロセスに動的に変 更を加え、「プローブ」と呼ばれる計測ポイン トを仕込むことができる。要はプローブを実行 することでdtrace側の処理を実行し、必要な記 録をとることができる。(OracleのWeb Pageの内 容を一部改) ● dtrace のプローブは、「プロバイダ」と呼ばれ るカーネルモジュールのセットから提供されて いる。 まあ、プロバイダはプローブを有効にするなど
  6. 6. もうちょい詳しく!その2 システムでサポートしているプロバイダとプ ローブの組はdtrace -lで表示できるよ。こんな 感じ。 ● # dtrace -l | head -n 10 ● ID PROVIDER MODULE FUNCTION NAME ● 1 dtrace BEGIN ● 4 fbt netbsd AES_GMAC_Final entry ● 5 fbt netbsd AES_GMAC_Final return
  7. 7. もうちょい詳しく!その3 プロセスごとのwriteシステムコールにかかる平均時間を求める fbt:netbsd:sys_write:entry { self->ts = timestamp; } fbt:netbsd:sys_write:return { @time[execname] = avg(timestamp – self->ts); self->ts = 0; }
  8. 8. もうちょい詳しく!その4 ● 先の実装例はプロセスごとのsys_write()にかか る平均時間を求めるものです。 ● ということは、sys_write()の先頭とreturnの箇所 で何らかの方法でdtrace処理が呼び出されない といけないはず・・・。
  9. 9. ここで疑問 ● プロバイダたるカーネルモジュールが動的に 「プローブ」を有効にすることはわかった。 ● しかし、「動的に有効」ってどうやってやって いるの? ● 実際、例に出てきたsys_write()読んでも怪しげ なマクロなどのプローブらしきものは出てこな いんだけど・・・。
  10. 10. ソースを探検する前に ● dtrace -lの結果から、システムコールに対応し ているプロバイダ(カーネルモジュール)はfbtの ようだ。 ● 超絶はしょりまくりでネタバレすると、dtrace のハンドリング(ロギング処理)をしているのは dtrace_probe()というdtraceカーネルモジュール 関数である。 ● dtraceカーネルモジュールはプロバイダではな くdtraceの処理を行うメインモジュールであ る。
  11. 11. ソースを探検!その1 ● dtrace_probe()はfbt_invop()から呼ばれており、 この関数はdtrace_invop_add()の引数で渡されて いるものである。このパターンは多分関数ポイ ンタの登録...? ● dtrace_invop_add()のソースは external/cddl/osnet/dev/dtrace/i386(amd64)/dtrace_s ubr.c である。もろアーキテクチャ依存な匂 い。
  12. 12. ソースを探検!その2 ● i386側の実装を見ることにする。 dtrace_invop_add()にはdtrace_invop_hdlrというハ ンドラ構造体がある。ここにfbt_invop()が登録 される。 ● 別のソースに実装されているdtrace_invop()では dtrace_invop_hdlrに登録した関数を呼び出して いる。
  13. 13. ソースを探検!その3 ● dtrace_invop()は、dtraceカーネルモジュールの アセンブラ関数でdtrace_invop_startと言う関数 から呼ばれている。 ● dtrace_invop_startのアドレスはdtraceの初期化関 数でdtrace_invop_jump_addrという変数に詰め込 まれている。 ● つまり、_dtrace_invop_jump_addrというポイン タ経由でdtrace_invop_start()が呼ばれているとい うことになる。
  14. 14. ソースを探検!その4 ● で、突き詰めていくと、dtrace_invop_jump_addr という関数ポインタに行き着く。 ● dtrace_invop_jump_addrはどこにあるのか? dtraceモジュールの中で呼んでいる箇所はな い。 ● で、カーネルのソースを調べてみると・・・ ● sys/arch/i386/i386/vector.S 内で呼んでいること がわかる。ベクタですよ、ベクタ。 ● 調べてみると、trap6のベクタから呼ばれている
  15. 15. ソースを探検!その5 ● ここまでをまとめると・・・ trap6の例外ベクタ --> dtrace_invop_jump_addr経 由でdtrace_invop_startをコール --> dtrace_invop_startから dtrace_invop()をコール --> dtrace_invop()ではdtrace_invop_add()であらかじ め登録されたdtrace_probe()をコール という非常にややこしいことになっています。 ● 起点はtrap6です。ええ。
  16. 16. 閑話休題、trap6とは? ● Intel® 64 and IA-32 Architectures Software Developer’s Manual 1846ページによると・・・ 「Interrupt 6—Invalid Opcode Exception (#UD)」 とあります。 ● 要するに不正命令例外です。
  17. 17. ソースを探検!その6 ● ここまでのところで、どうやら「不正命令」を 実行させることでtrap6を発動し、その勢いで dtraceの処理を呼び出すことがわかってきた。 ● でも、ビルド時にはない「不正命令」を各カー ネル関数にどうやって埋め込むのだろうか? ● 最初の方でお話ししたとおり、「dtraceスクリ プトで、プルーブを有効にしたときに」初めて dtrace処理が走りますが、これが肝。 ● つまり、dtraceでプルーブを有効にする処理を
  18. 18. ソースを探検!その7 ● これまた細かい途中経過をすっ飛ばすと、fbt カーネルモジュールのfbt_enable()という関数で プルーブを有効にしている。 ● その中に↓なコードがあるよん。 ● for (; fbt != NULL; fbt = fbt->fbtp_next) { ● *fbt->fbtp_patchpoint = fbt->fbtp_patchval; ● }
  19. 19. ソースを探検!その8 ● 前後の処理ではWrite Protectionを外 し、patchpointなるアドレスの指す箇所に patchvalという値を書き込んでいる。 ● 何となく、patchvalが「不正命令」でそれを patchpointが指す関数の頭と末尾に書き込んでい るのだろうことは推定がつく。 ● では、patchpointをどう特定しているのだろう か?
  20. 20. ソースを探検!その9 ● fbtp_patchpointおよびfbtp_patchvalは fbt_provide_module_cb()という関数で設定され ている。 ● この中では渡ってきたアドレスとサイズを使っ て命令の解析をしているようだ。 ● 関数先頭を判定するのに「push %ebp」かを見 たり、関数末尾を判定するのに「ret」であるか 見たり。 (他にもパターンはありますが、代表的なもの
  21. 21. ソースを探検!その10 ● なるほど。与えられた関数のアドレスとそのサ イズを使ってそこにある命令を解析しつつ、関 数の先頭と末尾を特定するのはわかりました。 ● そして、FBT_PATCHVALで定義される未定義 命令をpatchvalに、関数の先頭と末尾近辺のア ドレスをpatchpointに設定している。 ● もちろんpatchpointの指す元の命令はきちんと バックアップしてます!
  22. 22. ソースを探検!その11 ● では、関数のアドレスとそのサイズはどこから 取得しているの? ● 先にお話ししたfbt_provide_module_cb()は ksyms_mod_foreach()経由で呼ばれている。 ● ksyms_mod_foreach()は引数で指定したモジュー ル(カーネルモジュールやカーネル自身)のシン ボル群について都度指定した関数(ここでは fbt_provide_module_cb())を呼び出す。
  23. 23. ソースを探検!その12 ● シンボルやそのサイズはどこにあるの? ● 細かい事をはしょると、ELFの.symtabセクショ ンに存在する。 ● データフォーマットを知りたい?それなら http://www.skyfree.org/linux/references/ELF_Form at.pdf 内で「Elf32_Sym」をキーワードに検索してく れ!
  24. 24. というわけで強引にまとめ ● dtraceのトレース関数はtrap6経由で呼ばれる。 ● カーネルやカーネルモジュールの.symtabセク ションの情報を使って、関数のシンボルを獲得 している。 ● シンボル情報(アドレス、サイズ)を使って、そ れが指す命令群を解析して「不正命令」を埋め 込む場所を特定する。 ● dtraceのトレースが有効になったら、動的に 「不正命令」を埋め込んでtrap6を引き起こすこ
  25. 25. かなりはしょりまくりで乱暴でした が ● ご清聴ありがとうございましたm(_ _)m
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×