ldにおける変更
ldを使ってシンボルの置き換えをしているわけですが、これまで手元のバージョン(ld 2.20.1-system.20100303)だと、次のような振舞をしていました。
/* test.c */ extern int a; int main() { printf("a = %d\n",a); return 0; }
/* def_b.c */ int b = 42;
/* lscript */ a = b; EXTERN(b);
上記3つのファイルが在る時に
ld --version GNU ld (GNU Binutils for Ubuntu) 2.20.1-system.20100303 Copyright 2009 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty.
このldでは
gcc -c test.c def_b.c -- test.oとdef_b.oを作る ld -r test.o def_b.o lscript -o partial.o nm partial.o 00000000 D a 00000000 D b 00000000 T main U printf
ldのr(relocatable)オプションについてはここ( http://www.kpitgnutools.com/manuals/ld.html#IDX88 )などを。
ところが、ldの比較的新しいバージョン(以下はbinutilsから取って来た)
./ld-new --version GNU ld (GNU Binutils) 2.21 Copyright 2010 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty.
こっちのldを使うと、
./ld-new -r lscript def_b.o test.o -o partial2.o 00000000 A a 00000000 D b 00000000 T main U printf
このようにシンボルaが絶対アドレスを取るように成ってしまいます。
partial2.oはこの後問題が発生して
gcc partial.o -o exe1 ./exe1 => 42 gcc partial2.o -o exe2 ./exe2 => Segmantation Fault nm exe2 00000000 A a 0804a014 D b
となります。この変更はどの段階で入ったんでしょうかっていうのが。。。
ldに対するrオプションが本質的では恐らくなくて、例えば
gcc lscript test.o def_b.o -- ただしこのgccはリンク時に新しいldを使うものとする nm a.out 0804a014 A a 0804a014 D b
となるんですね。だから、リンカスクリプトの解釈が変わったんじゃないかなーという。
少なくとも、ld 2.20.51-system.20100908からはこうなってますね。