pdb.set_trace()
MacOSのPythonでrequestsパッケージを利用する
以下のようにpipでインストールできます。
$ sudo pip install requestspipのインストールについては、 こちら の記事を参照ください。
MacOSにpipをインストールする
1. インストーラをダウンロードする。
$ curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py > get-pip.py2. 実行する
$ sudo python get-pip.py
GDBの出力をフィルタする
GDBのPython機能を利用して、大量の出力から目的の行を抽出する方法を2つ紹介します。
1.reモジュールの利用(Pythonコードによる抽出)
1つ目は、backtraceの出力をPythonのreモジュールを使って目的の行を探します。主に青字の部分を目的に応じて変更してください。(gdb) py out=gdb.execute("i proc map", to_string=True); import re; [re.search("Named", line) and print(line) for line in out.split("\n")];
2.シェルを利用
2つ目は、コマンドラインのgrepを利用しています。単純な検索だとPythonのプログラム(それもワンライナー)を組むより容易に目的を達成できる場合もあるでしょう。(gdb) py a=gdb.execute("bt",to_string=True); import subprocess; subprocess.Popen("echo '%s' | grep main" % a, shell=True).wait()
なお、上記のいずれも技術的には、Pythonをワンライナを使用しています。
繰り返しはリスト包含(list comprehension)、分岐(if)にはand/orの遅延評価を利用しています。
関数はlamdaで変数にしています。使用例
通常、i proc mapコマンドを実行すると多くの行が出力されます。catコマンドを使って試してみましょう。$ gdb -q /bin/cat Reading symbols from /bin/cat...(no debugging symbols found)...done. (gdb) run Starting program: /bin/cat ^C <= 実行を中断するためにCTRL + Cを入力 Program received signal SIGINT, Interrupt. 0x00007ffff7afe6a0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81 81 ../sysdeps/unix/syscall-template.S: No such file or directory. (gdb) i proc maps Too many parameters: maps (gdb) i proc map process 19540 Mapped address spaces: Start Addr End Addr Size Offset objfile 0x400000 0x40b000 0xb000 0x0 /bin/cat 0x60a000 0x60b000 0x1000 0xa000 /bin/cat 0x60b000 0x60c000 0x1000 0xb000 /bin/cat 0x60c000 0x62d000 0x21000 0x0 [heap] 0x7ffff7a12000 0x7ffff7bcf000 0x1bd000 0x0 /lib/x86_64-linux-gnu/libc-2.17.so 0x7ffff7bcf000 0x7ffff7dcf000 0x200000 0x1bd000 /lib/x86_64-linux-gnu/libc-2.17.so 0x7ffff7dcf000 0x7ffff7dd3000 0x4000 0x1bd000 /lib/x86_64-linux-gnu/libc-2.17.so 0x7ffff7dd3000 0x7ffff7dd5000 0x2000 0x1c1000 /lib/x86_64-linux-gnu/libc-2.17.so 0x7ffff7dd5000 0x7ffff7dda000 0x5000 0x0 0x7ffff7dda000 0x7ffff7dfd000 0x23000 0x0 /lib/x86_64-linux-gnu/ld-2.17.so 0x7ffff7fcc000 0x7ffff7fcf000 0x3000 0x0 0x7ffff7ff8000 0x7ffff7ffa000 0x2000 0x0 0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso] 0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x22000 /lib/x86_64-linux-gnu/ld-2.17.so 0x7ffff7ffd000 0x7ffff7fff000 0x2000 0x23000 /lib/x86_64-linux-gnu/ld-2.17.so 0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack] 0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]上記では、マップされているライブラリの数がそれほど多くないので、目視で、目的のファイルを探すことも、それほど困難ではありませんが、firefoxやchromeのような大規模なプログラムでは数百行以上表示されます。 これを、stackの入っている行のみを表示させるには次のように入力します。かなりシンプルになることが理解いただけると思います。
(gdb) py out=gdb.execute("i proc map", to_string=True); import re; [re.search("stack", line) and print(line) for line in out.split("\n")];
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
参考
GDBからPython使用法については下記にも述べられています。 http://transparent-to-radiation.blogspot.jp/2014/01/gdbpython-script.htmlGDBでPython scriptを実行する
最近(少なくともversion 7以降)のGDBは、Python scriptを実行できます。実行には、従来のGDBマクロと同じくsourceコマンドを使用します。
早速、試してみましょう。次のようなPython scriptを用意します。
サンプルのデバッグ対象として以下のtarget.ccを使用します。
以下の例では、stacktrace出力の各行からframe番号と最後の単語を抽出して表示します。
早速、試してみましょう。次のようなPython scriptを用意します。
$ cat hello.py
#!/usr/bin/env python
import sys
sys.stdout.write('Hello, my first script.\n')
GDBを起動して、実行します。 (gdb) source hello.py Hello, my first script.
Python scriptからのGDB機能の利用
次に、Python scriptからGDBの機能を使用する例を紹介します。gdb.execute()関数を使用すれば、GDBのコマンドラインで行う操作を実行できます。サンプルのデバッグ対象として以下のtarget.ccを使用します。
[target.cc]
#include <cstdio>
#include <cstdlib>
#include <time.h>
int getval(int div)
{
return time(NULL) / div;
}
int main(void)
{
printf("val: %d\n", getval(5));
return EXIT_SUCCESS;
}
これをshow-bt.pyで次の4つのことを行います。
- break pointをgetval()関数の先頭に設定
- プログラムを実行
- break pointで停止時のbacktraceを表示する
- break pointで停止時のraxレジスタを表示する
[show-bt.py]
gdb.execute('b getval')
gdb.execute('run')
gdb.execute('bt')
gdb.execute('p/x $rax')
以下はコマンドラインからスクリプトを実行させる例です。
コマンドライン引数の-qは、GDB起動時のcopyrightなどの表示を抑制します。-xで実行するスクリプトファイルを指定します。
$ gdb -q -x show-bt.py target Reading symbols from /home/foo/target...done. Breakpoint 1 at 0x400627: file target.cc, line 7. Breakpoint 1, getval (div=5) at target.cc:7 7 return time(NULL) / div; #0 getval (div=5) at target.cc:7 #1 0x0000000000400656 in main () at target.cc:12 #2 0x00007ffff72d2ead in __libc_start_main (main=, argc= , ubp_av= , init= , fini= , rtld_fini= , stack_end=0x7fffffffe128) at libc-start.c:228 #3 0x0000000000400539 in _start () $1 = 0x7ffff763aee8
コマンドの出力をPythonの文字列として取得する
上記の例では、通常のGDBコマンドを実行するだけでしたが、この出力をPythonの文字列として取得してみましょう。これは、gdb.execute()関数のto_string引数にTrueを渡すことで実現できます。Pythonは、文字列処理も得意ですから、容易に特定の文字列を抽出したり、整形して表示することが可能になります。以下の例では、stacktrace出力の各行からframe番号と最後の単語を抽出して表示します。
$ cat show-bt-and-format.py
gdb.execute('b getval')
gdb.execute('run')
bt = gdb.execute('bt', to_string=True)
for line in bt.split('\n'):
words = line.split(' ')
print '%s %s' % (words[0], words[-1])
$ gdb -q -x show-bt-and-format.py target Reading symbols from /home/foo/target...done. Breakpoint 1 at 0x400627: file target.cc, line 7. Breakpoint 1, getval (div=5) at target.cc:7 7 return time(NULL) / div; #0 target.cc:7 #1 target.cc:12 #2 libc-start.c:228 #3 ()
登録:
投稿 (Atom)