Apple ldのalias_listオプションの挙動が良く分かりません その2
前回に引き続き。
% gcc --version i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % ld -v @(#)PROGRAM:ld PROJECT:ld64-97.17 llvm version 2.9svn, from Apple Clang 1.7 (build 77)
次の4ファイルを準備してそれに対してalias_listオプションを使ってみます。
/* h.h */ struct S { int *i; };
/* main.c */ #include "h.h" #include <stdio.h> extern int i; struct S bar = { &i }; extern void check(struct S*); int main() { printf("*bar.i = %d\n",*bar.i); check(&bar); return 0; }
/* lib.c */ #include "h.h" #include <stdio.h> #include <assert.h> extern struct S hogefuga; void check(struct S *p) { printf("*(p->i) = %d\n",*(p->i)); printf("*hogefuga.i = %d\n",*hogefuga.i); assert(p == &hogefuga); }
/* define_i.c */ int i = 42;
さて、今回は、lib.cの"hogefuga"シンボルを、main.cの"bar"シンボルへとリネームするべく、alias_listオプションに渡すファイルを次のように書きます。
% cat alias _bar _hogefuga
これを使って2バージョンのコンパイルをします。
% gcc -Wall -c main.c lib.c % gcc -Wall -c define_i.c % gcc -shared define_i.o -o define_i.so % gcc -o static main.o lib.o define_i.o -Wl,-alias_list,alias % gcc -o shared main.o lib.o define_i.so -Wl,-alias_list,alias
% nm static 0000000100000ee2 s stub helpers 0000000100001050 D _NXArgc 0000000100001058 D _NXArgv U ___assert_rtn 0000000100000ea7 s ___func__.2336 0000000100001068 D ___progname 0000000100000000 A __mh_execute_header 0000000100001070 D _bar 0000000100000e0d T _check 0000000100001060 D _environ U _exit 0000000100001070 D _hogefuga 0000000100001078 D _i 0000000100000ddc T _main U _printf 0000000100001000 s _pvars U dyld_stub_binder 0000000100000da0 T start
これは上手くいきそうですね!!
% nm shared 0000000100000ee2 s stub helpers 0000000100001058 D _NXArgc 0000000100001060 D _NXArgv U ___assert_rtn 0000000100000ea7 s ___func__.2336 0000000100001070 D ___progname 0000000100000000 A __mh_execute_header 0000000100001050 D _bar <- 0000000100000e0d T _check 0000000100001068 D _environ U _exit 0000000100001078 D _hogefuga <- U _i 0000000100000ddc T _main U _printf 0000000100001000 s _pvars U dyld_stub_binder 0000000100000da0 T start
!? 2つのシンボルのアドレスが異なっています…。
% ./static *bar.i = 42 *(p->i) = 42 *hogefuga.i = 42 % ./shared *bar.i = 42 *(p->i) = 42 zsh: segmentation fault ./shared
やはりsharedの方は失敗しました。
ちなみに、リンカスクリプトが渡せるldでは次のように書き
hogefuga = bar; EXTERN(bar);
EXTERNが必要かどうかは分かりませんが…、同様にコンパイルしてあげるとどちらも正しく動きます。