Intel Pinを使ってみる
Dynamic Binary Instrumentation(DBI)は実行時にバイナリの内容を書き換えることにより、CPU命令の単位でプログラム実行のトレースなどを行う手法である。 ここでは、x86/x64用のDBIツールであるIntel Pinを使ってみる。
環境
Ubuntu 14.04.4 LTS 64bit版
$ uname -a Linux vm-ubuntu64 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 14.04.4 LTS Release: 14.04 Codename: trusty $ gcc --version gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
なお、Intel Pinの実行ファイルが32 bit用バイナリであるため、ここでは「64 bitのUbuntu Linuxで32 bitの実行ファイルを動かす方法のメモ」に書いた方法で32 bit用バイナリも実行できるようにしてある。
Intel Pinのダウンロード
ダウンロードページからLinux用のCompiler Kitをダウンロードして展開する。
$ wget http://software.intel.com/sites/landingpage/pintool/downloads/pin-2.14-71313-gcc.4.4.7-linux.tar.gz $ tar xvf pin-2.14-71313-gcc.4.4.7-linux.tar.gz $ cd pin-2.14-71313-gcc.4.4.7-linux/
付属のコードを使ってみる
Intel Pinには、Pinを利用したさまざまなコードが最初から付属している。 ここではマニュアルを参考に、inscount0、itrace、pinatraceの三つのコードを使ってみる。
まずは、マニュアルで説明されているコード一式をコンパイルする。
$ cd source/tools/ManualExamples/ $ ls buffer_linux.cpp emudiv.cpp fork_jit_tool.cpp invocation.cpp malloc_mt.cpp safecopy.cpp staticcount.cpp buffer_windows.cpp fibonacci.cpp imageload.cpp isampling.cpp malloctrace.cpp stack-debugger.cpp strace.cpp countreps.cpp follow_child_app1.cpp inscount0.cpp itrace.cpp nonstatica.cpp stack-debugger-tutorial.sln thread_unix.c detach.cpp follow_child_app2.cpp inscount1.cpp little_malloc.c pinatrace.cpp stack-debugger-tutorial.vcxproj thread_win.c divide_by_zero_linux.c follow_child_tool.cpp inscount2.cpp makefile proccount.cpp stack-debugger-tutorial.vcxproj.filters w_malloctrace.cpp divide_by_zero_windows.c fork_app.cpp inscount_tls.cpp makefile.rules replacesigprobed.cpp statica.cpp $ make all TARGET=intel64
使おうとした際に次のようなエラーが出た場合は、指示に従ってカーネルオプションを変更しておく。
$ ../../../pin -t obj-intel64/inscount0.so -- /bin/ls E: Attach to pid 2301 failed. E: The Operating System configuration prevents Pin from using the default (parent) injection mode. E: To resolve this, either execute the following (as root): E: $ echo 0 > /proc/sys/kernel/yama/ptrace_scope E: Or use the "-injection child" option. E: For more information, regarding child injection, see Injection section in the Pin User Manual. E: Killed $ sudo sh -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
inscount0は、プログラム全体を通して実行された命令数をカウントする。
$ ../../../pin -t obj-intel64/inscount0.so -- /bin/ls buffer_linux.cpp emudiv.cpp fork_jit_tool.cpp inscount_tls.cpp makefile.rules pin.log stack-debugger-tutorial.vcxproj thread_win.c buffer_windows.cpp fibonacci.cpp imageload.cpp invocation.cpp malloc_mt.cpp proccount.cpp stack-debugger-tutorial.vcxproj.filters w_malloctrace.cpp countreps.cpp follow_child_app1.cpp inscount0.cpp isampling.cpp malloctrace.cpp replacesigprobed.cpp statica.cpp detach.cpp follow_child_app2.cpp inscount1.cpp itrace.cpp nonstatica.cpp safecopy.cpp staticcount.cpp divide_by_zero_linux.c follow_child_tool.cpp inscount2.cpp little_malloc.c obj-intel64 stack-debugger.cpp strace.cpp divide_by_zero_windows.c fork_app.cpp inscount.out makefile pinatrace.cpp stack-debugger-tutorial.sln thread_unix.c $ cat inscount.out Count 776214
itraceは、実行された命令のアドレスを順に出力する。
$ ../../../pin -t obj-intel64/itrace.so -- /bin/ls buffer_linux.cpp emudiv.cpp fork_jit_tool.cpp inscount_tls.cpp makefile pinatrace.cpp stack-debugger-tutorial.sln thread_unix.c buffer_windows.cpp fibonacci.cpp imageload.cpp invocation.cpp makefile.rules pin.log stack-debugger-tutorial.vcxproj thread_win.c countreps.cpp follow_child_app1.cpp inscount0.cpp isampling.cpp malloc_mt.cpp proccount.cpp stack-debugger-tutorial.vcxproj.filters w_malloctrace.cpp detach.cpp follow_child_app2.cpp inscount1.cpp itrace.cpp malloctrace.cpp replacesigprobed.cpp statica.cpp divide_by_zero_linux.c follow_child_tool.cpp inscount2.cpp itrace.out nonstatica.cpp safecopy.cpp staticcount.cpp divide_by_zero_windows.c fork_app.cpp inscount.out little_malloc.c obj-intel64 stack-debugger.cpp strace.cpp $ wc -l itrace.out 783915 itrace.out $ head itrace.out 0x7f49c3a802d0 0x7f49c3a802d3 0x7f49c3a83a70 0x7f49c3a83a71 0x7f49c3a83a74 0x7f49c3a83a76 0x7f49c3a83a78 0x7f49c3a83a7a 0x7f49c3a83a7c 0x7f49c3a83a7d
pinatraceは、プログラム全体を通して読み書きされたメモリのアドレスを出力する。
$ ../../../pin -t obj-intel64/pinatrace.so -- /bin/ls buffer_linux.cpp emudiv.cpp fork_jit_tool.cpp inscount_tls.cpp makefile pinatrace.cpp stack-debugger.cpp strace.cpp buffer_windows.cpp fibonacci.cpp imageload.cpp invocation.cpp makefile.rules pinatrace.out stack-debugger-tutorial.sln thread_unix.c countreps.cpp follow_child_app1.cpp inscount0.cpp isampling.cpp malloc_mt.cpp pin.log stack-debugger-tutorial.vcxproj thread_win.c detach.cpp follow_child_app2.cpp inscount1.cpp itrace.cpp malloctrace.cpp proccount.cpp stack-debugger-tutorial.vcxproj.filters w_malloctrace.cpp divide_by_zero_linux.c follow_child_tool.cpp inscount2.cpp itrace.out nonstatica.cpp replacesigprobed.cpp statica.cpp divide_by_zero_windows.c fork_app.cpp inscount.out little_malloc.c obj-intel64 safecopy.cpp staticcount.cpp $ wc -l pinatrace.out 308464 pinatrace.out $ head pinatrace.out 0x7f18a59b92d3: W 0x7ffd5acedde8 0x7f18a59bca70: W 0x7ffd5acedde0 0x7f18a59bca74: W 0x7ffd5aceddd8 0x7f18a59bca76: W 0x7ffd5aceddd0 0x7f18a59bca78: W 0x7ffd5aceddc8 0x7f18a59bca7a: W 0x7ffd5aceddc0 0x7f18a59bca7c: W 0x7ffd5aceddb8 0x7f18a59bca8f: R 0x7f18a5bdae70 0x7f18a59bca96: W 0x7f18a5bdac98 0x7f18a59bcaa7: R 0x7f18a5bdb000