BINARY HACKS #14-#19

c++filtについて
nm cpp.o
とすると、cppの名前マングリングによって、_Z3fooiのような読みづらいシンボルが得られる。
これは、
nm cpp.o | c++filt
nm –demangle cpp.o
によって解決できる。

addr2line(needs -g)
ポインタからソースコードの行を特定するためのコマンド。
addr2line -e ./a.out 0×8048764
-fオプションをつけることで、関数名もわかるようになる。
addr2line -e ./a.out 0×8048764

strip
ユーザのプログラムをstripして、開発者のところにしていないバイナリを残すと、コアファイルをコピーすることで開発環境でデバッグ可能。
strip ./a.out
-dオプションは、だいたい-gによる部分だけを削除する。すると、完全にデバッグできなくなる状況を避けられる。
strip -d ./a.out
.o, .aをstripするとシンボルが全部消えてしまう。

ar
作成(r: 新規挿入既存置換、c: 警告抑止, u: 新規のみ置換, s: ranlib)、閲覧、展開
ar rcus libhoge.a 1.o 2.o 3.o …
ar tv libhoge.a
ar xv libhoge.a

C++からCを呼び出す
一点のみ注意が必要である。Cのheaderで以下のようにすればよい。
#ifdef __cplusplus
extern “C” {
/*Cのコードいっぱい*/
}
#endif
extern “C”をつけると、C++の名前マングルの対象外となる。C++ではリンクが通れば型のミスはないと思われるが、Cでは間違ったプロトタイプ宣言が可能。extern “C”をつけた部分では、型の安全性がCレベルまで低下する。でも、普通に考えたらヘッダファイルが存在するはずなので、CからでもC++からでも使えるプロトタイプ宣言を作っておけば問題ない。
参考: http://hakobe932.hatenablog.com/entry/20090104/1231073299

CからC++を呼び出す
C++コードをg++でコンパイル、Cコードをgccでコンパイル、g++でリンクすることを考える。
4点注意が必要である。(1)(2)は「C++からCを呼び出す」の理由、(3)はCのコードにC++の例外が通るとプログラムが落ちることによる。
(1) C++のheaderをifdef, extern “C”でくくる。
#ifdef __cplusplus
extern “C” {
/*Cのコードいっぱい*/
}
#endif
(2) C++のソースをextern “C”でくくる
extern “C” {
int cpp_func(void) {return 0;}
}
(3) C++のソースが例外を投げるならば、例えば以下のようにする。
extern “C” {
int cpp_func(void) try {throw -1;} catch(…) {return -1}
}
(4) 関数ポインタを引数に取るCの関数は-fexceptionsでコンパイルしなければならない。このオプションをつけると、全ての関数についてフレーム解放処理を挿入する。
なお、glibcのqsort, bsearchなどは、このオプションをつけてコンパイルされている。

警告の出ない名前衝突–C言語
gccでたまに経験する、名前衝突しているのに何故か警告も出ずに、実行時に予想していないほうのシンボルが呼ばれるアレ。
これの原因は
(1) 静的ライブラリを作成する時のarコマンドは、ただのアーカイバなので、シンボル名とか見てない。
(2) 動的リンクのSONAMEとNEEDEDの対応付けも、一番初めに見つかった方を利用している。
逆に、回避可能な条件は以下である。
(1) 動的リンクを利用しておらず
(2) .oを全てまとめてリンクして実行ファイルを作成するとき

警告の出ない名前衝突–C++言語
C++ではもう一つ罠が増える。.oを全てまとめてリンクしていても期待したシンボルが参照されない可能性がある。
原因は、
(3) inlineで定義するweekシンボルがnon-weekシンボルの存在により無視されるから。これは.hの中に定義が入っていたとしたら、それが複数の.cppにincludeされると重複して定義されてしまうため、後で解決してやろうという気持ちによる。
回避方法は、
(3) inlineで定義するシンボルを作らない、もしくは、無名namespaceでリンケージリークを防ぐ。無名namespaceによってmoduleにシンボルを閉じ込めれば、当然モジュール内でしか利用できなくなるが、今回のような大域領域での名前衝突は解決できる。

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>