<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ものぐさ備忘録 &#187; gdbscript</title>
	<atom:link href="http://www.ginriki.net/wd/category/gdb/gdbscript-gdb/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ginriki.net/wd</link>
	<description>ソフトウェア関係の話を中心とした備忘録的日記</description>
	<lastBuildDate>Sun, 16 Jan 2011 20:07:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>rubyプロセスのコアファイルからバックトレースする。（おまけ: python）</title>
		<link>http://www.ginriki.net/wd/2009/11/09/80/</link>
		<comments>http://www.ginriki.net/wd/2009/11/09/80/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 22:00:34 +0000</pubDate>
		<dc:creator>ginriki</dc:creator>
				<category><![CDATA[FFI]]></category>
		<category><![CDATA[GDB]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[gdbscript]]></category>

		<guid isPermaLink="false">http://www.ginriki.net/wd/?p=80</guid>
		<description><![CDATA[某所で、「rubyプロセスがSEGVとかした時のコアファイルから、rubyスクリプトのバックトレースは取れるの？」って聞かれたので、ちょっと調べてみました。
結論としては、「rubyメソッドの呼び出し位置(ファイル名,  [...]]]></description>
			<content:encoded><![CDATA[<p>某所で、「rubyプロセスがSEGVとかした時のコアファイルから、rubyスクリプトのバックトレースは取れるの？」って聞かれたので、ちょっと調べてみました。</p>
<p>結論としては、「rubyメソッドの呼び出し位置(ファイル名, 行番号)は取れるけど、呼び出し時の実引数を見るのは難しい」っていう感じです。<br />
rubyのスタックフレームは、当然、rubyプロセスのメモリ上に構築されるので、スタックフレームのデータ構造さえわかれば、ある程度は表示できます。</p>
<p>ただ、コアファイルを出力したrubyプロセスはすでに存在しないので、ruby実装に使われているC関数をデバッガで（正確にはrubyプロセス上で）実行することができません。<br />
そのため、オブジェクトのinspectなどを実行することが難しく、実引数のオブジェクトが何か調べることが困難です。ということで、今回はスタックフレームを表示させる方法を以下で説明します。</p>
<p>rubyスタックフレームを表示するGDBスクリプトは以下になります(rb_dump.gdb)。<br />
(moriyoshiさんのブログ「<a href="http://d.hatena.ne.jp/moriyoshi/20070927/1190910311"> GDBで実行中のスクリプト言語のスタックフレームをダンプしてみる試み</a>」のコードをほとんどそのまま使わせていただきました。ありがとうございます。)</p>
<div class="igBar"><span id="lcode-4"><a href="#" onclick="javascript:showPlainTxt('code-4'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-4">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">define dump_rb_bt_from_core</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; set $t = ruby_frame</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; while $t</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; printf <span style="color:#CC0000;">"[0x%08x] "</span>, $t</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; if $t-&gt;<span style="">node</span>.<span style="">nd_file</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; printf <span style="color:#CC0000;">"(%s:%d)<span style="color:#000099; font-weight:bold;">\n</span>"</span>, $t-&gt;<span style="">node</span>.<span style="">nd_file</span>, <span style="color:#006600; font-weight:bold;">&#40;</span>$t-&gt;<span style="">node</span>.<span style="">flags</span>&gt;&gt; <span style="color:#800000;color:#800000;">19</span><span style="color:#006600; font-weight:bold;">&#41;</span> &amp; <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#800000;color:#800000;">1</span> &lt;&lt;<span style="color:#006600; font-weight:bold;">&#40;</span>sizeof<span style="color:#006600; font-weight:bold;">&#40;</span>NODE*<span style="color:#006600; font-weight:bold;">&#41;</span> * <span style="color:#800000;color:#800000;">8</span> - <span style="color:#800000;color:#800000;">19</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> - <span style="color:#800000;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; else</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; printf <span style="color:#CC0000;">"(UNKNOWN)<span style="color:#000099; font-weight:bold;">\n</span>"</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; end</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; set $t = $t-&gt;<span style="">prev</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; end</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">end</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">document dump_rb_bt_from_core</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; dumps the current frame stack from core file. <span style="">usage</span>: dump_rb_bt_from_core</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">end </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>今回はサンプルプログラムとして、0アドレスにアクセスするC拡張ライブラリを実行するrubyスクリプトを用意します。<br />
まず、C拡張ライブラリ(segv.c)、</p>
<div class="igBar"><span id="lc-5"><a href="#" onclick="javascript:showPlainTxt('c-5'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C:</span>
<div id="c-5">
<div class="c">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #339933;">#include &quot;ruby.h&quot;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">VALUE do_segv<span style="color: #66cc66;">&#40;</span>VALUE self<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; *<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">char</span>*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#40;</span>0x0<span style="color: #66cc66;">&#41;</span> = <span style="color: #cc66cc;color:#800000;">0</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> Qnil;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333;">void</span> Init_segv<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; VALUE module;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; module = rb_define_module<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"Segv"</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; rb_define_module_function<span style="color: #66cc66;">&#40;</span>module, <span style="color: #ff0000;">"do_segv"</span>, &amp;do_segv, <span style="color: #cc66cc;color:#800000;">0</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
で、後は適当にextconf.rbを作って、segv.soを作ります。</p>
<p>次にsegv.soを呼び出すRubyスクリプト(test.rb)。</p>
<div class="igBar"><span id="lruby-6"><a href="#" onclick="javascript:showPlainTxt('ruby-6'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-6">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> 'segv'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">def</span> test1<span style="color:#006600; font-weight:bold;">&#40;</span>a<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; test2<span style="color:#006600; font-weight:bold;">&#40;</span>a<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">def</span> test2<span style="color:#006600; font-weight:bold;">&#40;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; Segv::do_segv</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">test1<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>さて、サンプルプログラムの用意ができたので、SEGVさせてみます。</p>
<pre>
$ ulimit -c unlimited
$ ruby test.rb
test.rb:8: [BUG] Segmentation fault
ruby 1.8.5 (2006-08-25) [i386-linux]

アボートしました (core dumped)
</pre>
<p>これでコアファイルが出力されたので、それをGDBで解析します。</p>
<p>今回はCentOS 5.3のyumでインストールしたrubyから出力されたコアファイルなので、<br />
GDBで解析するには、<a href="http://debuginfo.centos.org/">ここ</a>からrubyのdebuginfoをインストールしておく必要があります。</p>
<pre>
$ wget http://debuginfo.centos.org/5/i386/ruby-debuginfo-1.8.5-5.el5_3.7.i386.rpm
# rpm -i ruby-debuginfo-1.8.5-5.el5_3.7.i386.rpm
</pre>
<p>それでは、GDBでコアファイルからrubyのバックトレースをさせてみます。</p>
<pre>
$ gdb ruby core.29443
GNU gdb Fedora (6.8-37.el5)
...
(gdb) backtrace   #通常のC関数レベルのバックトレース。
#0  0x00b3a402 in __kernel_vsyscall ()
#1  0x0056fdf0 in raise () from /lib/libc.so.6
#2  0x00571701 in abort () from /lib/libc.so.6
#3  0x00c514c2 in rb_bug (fmt=<value optimized out>) at error.c:214
#4  0x00cbd80b in sigsegv (sig=<value optimized out>) at signal.c:537
#5  [signal handler called]
#6  do_segv (self=3086662140) at segv.c:4
#7  0x00c54dd5 in call_cfunc (...) at eval.c:5657
#8  0x00c5c4ab in rb_call0 (...) at eval.c:5810

(gdb) source rb_dump.gdb      #この記事の最初に作ったGDBスクリプトをロード
(gdb) dump_rb_bt_from_core  # rubyバックトレース
[0xbfc1da20] (test.rb:8)
[0xbfc1e0e0] (test.rb:4)
[0xbfc1e7c0] (test.rb:11)
[0x00d0f960] Cannot access memory at address 0x4
</pre>
<p>以上になります。</p>
<p>pythonもコアファイルからスタックフレームが取れるか調べてみましたが、<br />
<a href="http://wiki.python.org/moin/DebuggingWithGdb">DebuggingWithGDB</a>のgdbinitスクリプトを読む限り、<br />
rubyと同様に実行していたpythonスクリプトのファイル名と行番号は取れそうです。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ginriki.net/wd/2009/11/09/80/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IA-32のjmp, call命令でTrapするGDBスクリプト</title>
		<link>http://www.ginriki.net/wd/2008/12/03/48/</link>
		<comments>http://www.ginriki.net/wd/2008/12/03/48/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 12:30:05 +0000</pubDate>
		<dc:creator>ginriki</dc:creator>
				<category><![CDATA[GDB]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[debugger]]></category>
		<category><![CDATA[gdbscript]]></category>

		<guid isPermaLink="false">http://www.gikogeek.net/wd/?p=48</guid>
		<description><![CDATA[jmp/call命令の実行直前までプログラムを進めるGDBスクリプトです。
こういう用途に使えるGDBコマンドがないようなので、自分で作りました。
必要な方はご自由に使ってください。
- script.gdb
使い方は以 [...]]]></description>
			<content:encoded><![CDATA[<p>jmp/call命令の実行直前までプログラムを進めるGDBスクリプトです。<br />
こういう用途に使えるGDBコマンドがないようなので、自分で作りました。<br />
必要な方はご自由に使ってください。<br />
- <a href="http://www.ginriki.net/wd/wp-content/uploads/2008/12/script.gdb">script.gdb</a></p>
<p>使い方は以下の通り、</p>
<pre>$ gdb a.out
(gdb) source script.gdb
(gdb) break main
(gdb) run
＃ main関数でbreak

(gdb) run_until_call_jmp
＃ main関数内のcall or jmp命令直前で停止</pre>
<h4>jmp,call命令のop codeの調べ方</h4>
<p>IA-32命令セットにおける、JMP, CALLのオペコードは下記の通りになりますIA-32 インテル アーキテクチャ・ソフトウェア・ディベロッパーズ・マニュアル 中巻より抜粋。<a href="http://www.intel.com/jp/download/index.htm">http://www.intel.com/jp/download/index.htm</a></p>
<p><a href="http://www.gikogeek.net/wd/wp-content/uploads/2008/12/jmp_op.png"><img class="aligncenter size-full wp-image-49" title="jmp_op" src="http://www.gikogeek.net/wd/wp-content/uploads/2008/12/jmp_op.png" alt="JMP命令のオペコード" width="500" height="154" /></a><br />
<a href="http://www.gikogeek.net/wd/wp-content/uploads/2008/12/call_op1.png"><img class="aligncenter size-full wp-image-51" title="call_op1" src="http://www.gikogeek.net/wd/wp-content/uploads/2008/12/call_op1.png" alt="callオペコード" width="499" height="140" /></a></p>
<p>cb、cw、cd、cpは、オペコードの後に続く1,2,4,6バイトの値です。<br />
jmpやcall命令では、jmp/call先のアドレス値を表しています。</p>
<p>/2とか/3とかっていうのは、ModR/Mバイトのdigit(＝ op codeの一部) 上記マニュアルの2章（特に2.4～2.6)参照を表してます。<br />
op codeの一部なので、当然、命令を判定する際にdigitのチェックが必要です。</p>
<p>digitは/0～/7まであり、ModR/Mバイトの下位3bitに対応します。</p>
<p>例えば32bitの絶対間接nearジャンプのオペコードは下記になります。</p>
<pre>16進表記:  FF /4
2進表記 :  11111111 xxxxx100</pre>
<p>xxxxxの部分の値によって、ジャンプ先のアドレス値として参照するレジスタ/メモリアドレスが変化します。<br />
例えば、eaxレジスタに格納されたアドレス値へジャンプする場合は、xxxxx=11000 です。</p>
<p>こんな感じで命令のop codeを調べて実装したのが上記のGDBスクリプトです。<br />
スクリプトを改造する時の参考にしてください。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ginriki.net/wd/2008/12/03/48/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

