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.html
0 件のコメント:
コメントを投稿