waekシンボル
ceil関数からを調べていたらcuomo@karky7 ~ $ nm -D /lib64/libm-2.17.so | grep ceil 000000000001a810 i ceil 0000000000030220 i ceilf 0000000000039a70 W ceill cuomo@karky7 ~ $ceil関数を調べていてnmコマンドのWをみて、「これ何だっけ?」と半分忘れかかっていたので脱線...
weakシンボルとは書き換え可能な変数、または関数名(関数のエントリアドレス)で、同名称が非weakシンボルで名前解決される場合はそちらが利用される位しか覚えていませんがあってるかどうかわからない。 でこんな感じ、
int main () { test(); return 0; }
#include#include extern long double ceill(long double x) __attribute__ ((weak)); void test(void) { if (ceill) { printf("%Lf\n", ceill(15000 * 1.08)); } else { printf("ceillなんて実装してねぇし\n"); } }
ビルド方法
ceil.so共有ライブラリを作成し、それをmain.cへリンクさせる
cuomo@karky7 ~ $ gcc -fPIC -shared -o ceil.so ceil.c cuomo@karky7 ~ $ gcc main.c ./ceil.soこれを普通に実行してみると
cuomo@karky7 ~ $ ./a.out ceillなんて実装してねぇし cuomo@karky7 ~ $これはceill関数にリンクできていないから呼び出ない、これをこうすると
cuomo@karky7 ~ $ LD_PRELOAD=/lib64/libm.so.6 ./a.out 16201.000000 cuomo@karky7 ~ $LD_PRELOADでlibmをしてするとちゃんとceillがリンクされて実行できる。
まとめると
GCC GNU拡張のアトリビュート__attribute__でweekを使うと、リンク時に-lmを指定しなくてもリンクできるようになる。
extern long double ceill(long double x) __attribute__ ((weak));もしこれを書かないと、-lmで明示的にリンクが必要になる
cuomo@karky7 ~ $ gcc -fPIC -shared -lm -o ceil.so ceil.cさらに、実行時に名前解決できない場合、そのシンボルが0で初期化されて、コード(a.out)自体は実行が可能になる、そうじゃないと実行時のリンクエラーで、コード(a.out)の実行ができない。 という、よくわからない説明ですが、そういう風になっていると思います。
0 件のコメント:
コメントを投稿