Pebble Coding

ソフトウェアエンジニアによるIT技術、数学の備忘録

C++のシンボルテーブル

macにはnmというシンボルを見るコマンドがあります。

namespace MyNameSpace {

class MyObject {
public:
MyObject();
};

MyObject::MyObject()
{
printf("aa\n");
}

}

上記のコードをダイナミックリンクでコンパイルしたモジュールの出力をみてみます。


$ nm aa
0000000000000f70 T __ZN11MyNameSpace8MyObjectC1Ev
0000000000000f50 T __ZN11MyNameSpace8MyObjectC2Ev
0000000000002008 d __dyld_private
U _printf
U dyld_stub_binder

シンボルタイプの意味は以下です。

t - symbol is in the text (code) section - local
T - symbol is in the text (code) section - global/external
U - symbol is undefiend - global/external
b - symbol is in the uninitialized data (BSS) section - local
w - symbol is a weak symbol that has not been specifically tagged as a weak symbol
A - symbol value wont be changed by further linking - global/external
s - section symbol, local
S - section symbol, global

どうやら大文字がglobal/external、小文字がlocalのようです。

Xcodeの設定では、Symbols Hidden by Default がNoになっていますが、
Yesに変更してもう一度試してみますが変化なしです。

Other C++ Flags に -fvisibility=hidden を指定して試してみます。


$ nm aa
0000000000000f70 t __ZN11MyNameSpace8MyObjectC1Ev
0000000000000f50 t __ZN11MyNameSpace8MyObjectC2Ev
0000000000002008 d __dyld_private
U _printf
U dyld_stub_binder

最初の2つのTが小文字のtに変わりました。
わかりやすいように別の表示でみてみます。


nm

-C Decode (demangle) low-level symbol names into user-level names.
-D Display the dynamic symbols rather than the normal symbols, which is
only meaningful for shared libraries.
-g Display only external symbols.
-a Display all symbols, even debugger-only symbols.


$ nm -C aa
0000000000000f70 t MyNameSpace::MyObject::MyObject()
0000000000000f50 t MyNameSpace::MyObject::MyObject()
0000000000002008 d __dyld_private
U _printf
U dyld_stub_binder

C++のクラスのコンストラクタのシンボルがグローバルからローカルに変わったことを表しています。
要するにこのダイナミックリンクライブラリのこのシンボルが外部から呼び出せなくなったことを表します。

これはstaticをつけないC関数においても同じです。staticをつけたCの関数は内部リンケージと呼ばれシンボルテーブルにすらのらなくなります。

参考:

Shared Library Symbol Conflicts (on Linux)