Simon Atanasyan
2014-Dec-08 06:22 UTC
[LLVMdev] [lld] Handling multiple -init/-fini command line options
Hi, The LLD linker in gnu flavor mode accepts multiple -init/-fini command line options. For _all_ symbols specified by these options the linker creates appropriate entries in the .init_array/.fini_array sections. But it looks like LD and Gold linkers do not support this feature and take in account only the last -init/-fini options. % cat foo.c int a = 0; void foo() { a += 1; } void bar() { a += 2; } % cat main.c extern int a; int printf(const char *, ...); int main() { printf("a: %d\n", a); } % gcc -fPIC -shared -o libfoo.so -Wl,-init,foo -Wl,-init,bar foo.c % gcc main.c -L. -lfoo -Wl,-rpath,. % ./a.out 2 % gcc -fPIC -shared -o libfoo.so -Wl,-init,bar -Wl,-init,foo foo.c % ./a.out 1 What is the reason of this incompatibility? The question is caused by attempt to support DT_INIT/DT_FINI dynamic table tags. The table can contain no more than one DT_INIT/DT_FINI tags. The LD and Gold linker look up either default symbols (_init/_fini) or symbols specified by the -init/-fini options and put their values to the tags. -- Simon Atanasyan
Rui Ueyama
2014-Dec-08 06:35 UTC
[LLVMdev] [lld] Handling multiple -init/-fini command line options
I don't know whether or not it's intended, but it seems like a subtle but unnecessary incompatibility. I'd vote for making it compatible with GNU unless there's a real reason to not do so. On Mon, Dec 8, 2014 at 3:22 PM, Simon Atanasyan <simon at atanasyan.com> wrote:> Hi, > > The LLD linker in gnu flavor mode accepts multiple -init/-fini command > line options. For _all_ symbols specified by these options the linker > creates appropriate entries in the .init_array/.fini_array sections. > But it looks like LD and Gold linkers do not support this feature and > take in account only the last -init/-fini options. > > % cat foo.c > int a = 0; > void foo() { a += 1; } > void bar() { a += 2; } > > % cat main.c > extern int a; > int printf(const char *, ...); > int main() { printf("a: %d\n", a); } > > % gcc -fPIC -shared -o libfoo.so -Wl,-init,foo -Wl,-init,bar foo.c > % gcc main.c -L. -lfoo -Wl,-rpath,. > % ./a.out > 2 > > % gcc -fPIC -shared -o libfoo.so -Wl,-init,bar -Wl,-init,foo foo.c > % ./a.out > 1 > > What is the reason of this incompatibility? The question is caused by > attempt to support DT_INIT/DT_FINI dynamic table tags. The table can > contain no more than one DT_INIT/DT_FINI tags. The LD and Gold linker > look up either default symbols (_init/_fini) or symbols specified by > the -init/-fini options and put their values to the tags. > > -- > Simon Atanasyan > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141208/2ddf8d3c/attachment.html>
Shankar Easwaran
2014-Dec-08 16:21 UTC
[LLVMdev] [lld] Handling multiple -init/-fini command line options
This is a bug with the Gnu linker, IMO. There is also some behavioral difference for static executables when the -init/-fini options are used too. The DT_INIT/DT_FINI correspond to one initializer function,where as DT_INIT_ARRAY/DT_FINI_ARRAY is used when there is more than one initalizer function/finalizer function respectively. You could ask this same question in the binutils forums, but I think we should use DT_INIT_ARRAY/DT_FINI_ARRAY if more than one init/fini function is supplied by the user. Shankar Easwaran On 12/8/2014 12:22 AM, Simon Atanasyan wrote:> Hi, > > The LLD linker in gnu flavor mode accepts multiple -init/-fini command > line options. For _all_ symbols specified by these options the linker > creates appropriate entries in the .init_array/.fini_array sections. > But it looks like LD and Gold linkers do not support this feature and > take in account only the last -init/-fini options. > > % cat foo.c > int a = 0; > void foo() { a += 1; } > void bar() { a += 2; } > > % cat main.c > extern int a; > int printf(const char *, ...); > int main() { printf("a: %d\n", a); } > > % gcc -fPIC -shared -o libfoo.so -Wl,-init,foo -Wl,-init,bar foo.c > % gcc main.c -L. -lfoo -Wl,-rpath,. > % ./a.out > 2 > > % gcc -fPIC -shared -o libfoo.so -Wl,-init,bar -Wl,-init,foo foo.c > % ./a.out > 1 > > What is the reason of this incompatibility? The question is caused by > attempt to support DT_INIT/DT_FINI dynamic table tags. The table can > contain no more than one DT_INIT/DT_FINI tags. The LD and Gold linker > look up either default symbols (_init/_fini) or symbols specified by > the -init/-fini options and put their values to the tags. >-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
Will Newton
2014-Dec-08 17:08 UTC
[LLVMdev] [lld] Handling multiple -init/-fini command line options
On 8 December 2014 at 16:21, Shankar Easwaran <shankare at codeaurora.org> wrote:> This is a bug with the Gnu linker, IMO. There is also some behavioral > difference for static executables when the -init/-fini options are used too. > > The DT_INIT/DT_FINI correspond to one initializer function,where as > DT_INIT_ARRAY/DT_FINI_ARRAY is used when there is more than one initalizer > function/finalizer function respectively. > > You could ask this same question in the binutils forums, but I think we > should use DT_INIT_ARRAY/DT_FINI_ARRAY if more than one init/fini function > is supplied by the user.One reason why this behaviour is useful in the GNU world is if the compiler adds an -init flag then the user can add CFLAGS="-Wl,-init,foo" and override what the compiler passes without causing an error. How useful this is in this particular case I am not sure but it holds true for some linker options.> On 12/8/2014 12:22 AM, Simon Atanasyan wrote: >> >> Hi, >> >> The LLD linker in gnu flavor mode accepts multiple -init/-fini command >> line options. For _all_ symbols specified by these options the linker >> creates appropriate entries in the .init_array/.fini_array sections. >> But it looks like LD and Gold linkers do not support this feature and >> take in account only the last -init/-fini options. >> >> % cat foo.c >> int a = 0; >> void foo() { a += 1; } >> void bar() { a += 2; } >> >> % cat main.c >> extern int a; >> int printf(const char *, ...); >> int main() { printf("a: %d\n", a); } >> >> % gcc -fPIC -shared -o libfoo.so -Wl,-init,foo -Wl,-init,bar foo.c >> % gcc main.c -L. -lfoo -Wl,-rpath,. >> % ./a.out >> 2 >> >> % gcc -fPIC -shared -o libfoo.so -Wl,-init,bar -Wl,-init,foo foo.c >> % ./a.out >> 1 >> >> What is the reason of this incompatibility? The question is caused by >> attempt to support DT_INIT/DT_FINI dynamic table tags. The table can >> contain no more than one DT_INIT/DT_FINI tags. The LD and Gold linker >> look up either default symbols (_init/_fini) or symbols specified by >> the -init/-fini options and put their values to the tags. >> > > > -- > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by > the Linux Foundation > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-- Will Newton Toolchain Working Group, Linaro
Joerg Sonnenberger
2014-Dec-08 17:09 UTC
[LLVMdev] [lld] Handling multiple -init/-fini command line options
On Mon, Dec 08, 2014 at 10:21:49AM -0600, Shankar Easwaran wrote:> The DT_INIT/DT_FINI correspond to one initializer function,where as > DT_INIT_ARRAY/DT_FINI_ARRAY is used when there is more than one > initalizer function/finalizer function respectively.This is not true. The difference is that the DT_INIT / DT_FINI function is responsible for calling into the .init / .fini block and for DT_INIT_ARRAY / DT_FINI_ARRAY, the block is explicitly defined as a list of pointers and it is the responsibility of either the CRT logic or the dynamic linker to call them. That said, I don't think more than one DT_INIT / DT_FINI entry should be allowed as the latter entry will overwrite the earlier ones. Joerg
Michael Spencer
2014-Dec-08 23:41 UTC
[LLVMdev] [lld] Handling multiple -init/-fini command line options
On Sun, Dec 7, 2014 at 10:35 PM, Rui Ueyama <ruiu at google.com> wrote:> I don't know whether or not it's intended, but it seems like a subtle but > unnecessary incompatibility. I'd vote for making it compatible with GNU > unless there's a real reason to not do so.I agree. We should do whatever GNU ld does here. - Michael Spencer> > On Mon, Dec 8, 2014 at 3:22 PM, Simon Atanasyan <simon at atanasyan.com> wrote: >> >> Hi, >> >> The LLD linker in gnu flavor mode accepts multiple -init/-fini command >> line options. For _all_ symbols specified by these options the linker >> creates appropriate entries in the .init_array/.fini_array sections. >> But it looks like LD and Gold linkers do not support this feature and >> take in account only the last -init/-fini options. >> >> % cat foo.c >> int a = 0; >> void foo() { a += 1; } >> void bar() { a += 2; } >> >> % cat main.c >> extern int a; >> int printf(const char *, ...); >> int main() { printf("a: %d\n", a); } >> >> % gcc -fPIC -shared -o libfoo.so -Wl,-init,foo -Wl,-init,bar foo.c >> % gcc main.c -L. -lfoo -Wl,-rpath,. >> % ./a.out >> 2 >> >> % gcc -fPIC -shared -o libfoo.so -Wl,-init,bar -Wl,-init,foo foo.c >> % ./a.out >> 1 >> >> What is the reason of this incompatibility? The question is caused by >> attempt to support DT_INIT/DT_FINI dynamic table tags. The table can >> contain no more than one DT_INIT/DT_FINI tags. The LD and Gold linker >> look up either default symbols (_init/_fini) or symbols specified by >> the -init/-fini options and put their values to the tags. >> >> -- >> Simon Atanasyan >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >