<?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; アセンブリ</title>
	<atom:link href="http://www.ginriki.net/wd/category/%e3%82%a2%e3%82%bb%e3%83%b3%e3%83%96%e3%83%aa/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>static変数に対応するアドレスを探す(ELF format編）</title>
		<link>http://www.ginriki.net/wd/2007/06/19/19/</link>
		<comments>http://www.ginriki.net/wd/2007/06/19/19/#comments</comments>
		<pubDate>Tue, 19 Jun 2007 13:51:02 +0000</pubDate>
		<dc:creator>ginriki</dc:creator>
				<category><![CDATA[アセンブリ]]></category>
		<category><![CDATA[バイナリ]]></category>

		<guid isPermaLink="false">http://www.gikogeek.net/wd/?p=19</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<div class="section">
<p>共有ライブラリ上に存在する、あるstatic変数aのプロセス上でのアドレスを知りたいときがあります。apt-getでインストールした共有ライブラリをデバッグしたい時なんかがそうです。</p>
<p>最近、こういったアドレスを探すことが多いので、忘れないようにメモっておきます。</p>
<p></p>
<p>以下の話は、共有ライブラリが位置独立コード（PIC)としてコンパイルされていることを前提にしています。</p>
<p>あと、私はgccとx86系cpuを使って確認しているので、他の環境だと違う場合があります。</p>
<p></p>
<h4>基本</h4>
<p>共有ライブラリを使っているプロセスのメモリ利用状況をpmapコマンドやprocファイルシステムを使って確認することで、共有ライブラリのロード先がわかります。</p>
<p>共有ライブラリ名がhoge.soだとすると、</p>
<pre class="syntax-highlight">
$ pmap <span class="synConstant">10000</span>
<span class="synConstant">08048000</span>    4K <span class="synStatement">r</span>-x-- a.out
...<span class="synStatement">&#60;</span>略<span class="synStatement">&#62;</span>...
b7f8e000    8K rwx-- foo.so
b7f94000    4K <span class="synStatement">r</span>-x-- hoge.so
b7f95000    4K rwx-- hoge.so
...<span class="synStatement">&#60;</span>略<span class="synStatement">&#62;</span>...
</pre>
<p>上のpmapの結果から</p>
<p>hoge.soのロード先先頭アドレスは、b7f94000だとわかります。また、シンボルテーブルにstatic変数aの情報があるなら、簡単にaの共有ライブラリ内での相対アドレスがわかります。</p>
<p>あとは、以下の計算式、</p>
<p> (プロセス上での変数aのアドレス） = (共有ライブラリのロード先頭アドレス) + (変数aの相対アドレス)</p>
<p>で変数aのアドレスがわかります。</p>
<p>まあ、こんなのいちいち計算しなくても、gdbがやってくれます。gdbでプロセスにアタッチして、</p>
<pre class="syntax-highlight">
<span class="synStatement">p</span> &#38;a
</pre>
<p>とかすれば、変数aのアドレスがわかります。</p>
<h4>シンボルテーブルがない場合</h4>
<p>apt-getでインストールした共有ライブラリの場合、ファイルサイズを減らすために、シンボルテーブルがstripコマンドで削除されていることがあります。</p>
<p>この場合、簡単には変数aの相対アドレスを知ることができません。プログラムを実行させずに相対アドレスを調べるには、アセンブリコードを読んで相対アドレスを探すしかないです<span class="footnote"><a href="/gikogeek/#f1" name="fn1" title="ちなみに、staticではない大域変数なら、objdump -Tとか、nm -D とかして、ダイナミックシンボルテーブルから、相対アドレスを調べれば十分です。">*1</a></span>（たぶん）。</p>
<p>アセンブリコードだけでもよくわからないので、コンパイル元のソースコードも使います。</p>
<p>まず、ソースコードの中で変数aを操作する処理が入っているグローバル関数をまず探します。グローバル関数の中で変数aを操作していないのなら、グローバル関数からたどりやすい関数の内、変数aを操作する関数を探します。グローバル関数の相対アドレスは、ダイナミックシンボルテーブルに存在するので、objdumpで逆アセンブルした時、objdumpが適切にグローバル関数の先頭を表示してくれます。</p>
<p>最適化が影響しないかぎり、グローバル関数を基点として、ソースコードとアセンブリコードを比較していけば、変数aのGOTからの相対アドレスを判別できるアセンブリ命令が見つかると思います。</p>
<p>例えば、以下のソースコード、</p>
<pre class="syntax-highlight">
a = <span class="synConstant">0</span>;
</pre>
<p>に対応するアセンブリコード</p>
<pre class="syntax-highlight">
<span class="synIdentifier">movl</span> $<span class="synConstant">0x0</span> <span class="synConstant">0x20</span>(%<span class="synIdentifier">ebx</span>)
</pre>
<p>を見つけたとします。</p>
<p>0&#215;20が、変数aのGOTからの相対アドレスです。</p>
<p>このとき、%ebxは、</p>
<p> %ebx = (ファイル内のGOT相対アドレス） + (共有ライブラリロード先頭アドレス）</p>
<p>です。</p>
<p>ファイル内のGOT相対アドレスは、objdump -Tコマンドで表示されるダイナミックシンボルテーブルのうち、</p>
<p> _GLOBAL_OFFSET_TABLE_シンボルのアドレスに対応します(gccの場合）</p>
<p>また、(_GLOBAL_OFFSET_TABLE_のアドレス) == (.got.pltセクションのアドレス）のようです。</p>
<p>共有ライブラリロード先頭アドレスは、最初の方法と同様にpmapコマンドを使って見つけられます。</p>
<p>以上の情報を使って、以下の計算式、</p>
<p>　(プロセス上での変数aのアドレス） = (変数aのGOTからの相対アドレス) + (_GLOBAL_OFFSET_TABLE_のアドレス) + (共有ライブラリロード先頭アドレス）</p>
<p>で変数aのアドレスがわかります。</p>
<p>うーん、何か説明がわかりにくいなあ。実際にアドレスを探している動画とか作ったほうがわかりやすいかも。</p>
<h4>参考文献</h4>
<p>GOTとかPICとかについては、以下の書籍が参考になります。</p>
</p>
<div class="hatena-asin-detail">
<a href="http://d.hatena.ne.jp/rakuten/book/11004181"><img src="http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/2740/27406437.jpg?_ex=128x128" class="hatena-asin-detail-image" alt="Linkers ＆ loaders" title="Linkers ＆ loaders"></a></p>
<div class="hatena-asin-detail-info">
<p class="hatena-asin-detail-title"><a href="http://d.hatena.ne.jp/rakuten/book/11004181">Linkers ＆ loaders</a></p>
<ul>
<li><span class="hatena-asin-detail-label">ジャンル:</span> <a href="http://hb.afl.rakuten.co.jp/hgc/03dc3250.fca9e043.03dc3251.3135e3f9/?pc=http%3A%2F%2Fbeta.directory.rakuten.co.jp%2Frms%2Fsd%2Fdirectory%2Fvc%2Fs1tz200162%2F" target="_blank">本・雑誌・コミック</a> &#62; <a href="http://hb.afl.rakuten.co.jp/hgc/03dc3250.fca9e043.03dc3251.3135e3f9/?pc=http%3A%2F%2Fbeta.directory.rakuten.co.jp%2Frms%2Fsd%2Fdirectory%2Fvc%2Fs1tz101287%2F" target="_blank">PC・システム開発</a> &#62; <a href="http://hb.afl.rakuten.co.jp/hgc/03dc3250.fca9e043.03dc3251.3135e3f9/?pc=http%3A%2F%2Fbeta.directory.rakuten.co.jp%2Frms%2Fsd%2Fdirectory%2Fvc%2Fs1tz101937%2F" target="_blank">その他</a></li>
<li><span class="hatena-asin-detail-label">ショップ:</span> <a href="http://hb.afl.rakuten.co.jp/hgc/03dc3250.fca9e043.03dc3251.3135e3f9/?pc=http%3A%2F%2Fwww.rakuten.co.jp%2Fbook%2F" target="_blank">楽天ブックス</a></li>
<li><span class="hatena-asin-detail-label">価格:</span> 3,360円</li>
</ul>
</div>
<div class="hatena-asin-detail-foot"></div>
</div>
</div>
<div class="footnote">
<p class="footnote"><a href="/gikogeek/#fn1" name="f1">*1</a>：ちなみに、staticではない大域変数なら、objdump -Tとか、nm -D とかして、ダイナミックシンボルテーブルから、相対アドレスを調べれば十分です。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.ginriki.net/wd/2007/06/19/19/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

