https://sourceware.org/bugzilla/show_bug.cgi?id=23870
Bug ID: 23870 Summary: gold does not resolve the address of main when main is in a shared library Product: binutils Version: 2.31 Status: NEW Severity: normal Priority: P2 Component: gold Assignee: ccoutant at gmail dot com Reporter: stephen.kim at oracle dot com CC: ian at airs dot com Target Milestone: --- This is reproducible on aarch64. I got notice this issue due to the Go tools. However, here is the reduced test case purely in C. When a PIC shared library that has the "main" function is linked against a non-PIC .o file to form a non-PIE executable, Gold and the GNU linker both use crti.o. Only Gold does not find the address of main properly. The address is 0 in the generated executable, which leads the segmentation fault at runtime. Here is my reduced example: $ cat main.c #include <stdio.h> extern int foo(int, int); int main() { printf("%d\n", foo(1, 3)); return 0; } $ cat foo.c int __attribute__ ((noinline)) foo(int x, int y) { return x & y; } $ gcc -o main.o -fPIC -c main.c $ gcc -shared -o libmain.so main.o $ gcc -o foo.o -c foo.c $ gcc -fuse-ld=gold -o a.out -lmain -L$PWD -Wl,-v,-rpath=$PWD foo.o collect2 version 4.8.5 20150623 (Red Hat 4.8.5-28.0.4) /usr/bin/ld.gold --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -o a.out /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/crtbegin.o -L/home/aion1223/shared -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../.. -lmain -v -rpath=/home/aion1223/shared foo.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/aarch64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crtn.o GNU gold (version 2.27-28.base.0.2.el7_5.1) 1.12 $ ./a.out Segmentation fault (core dumped) If I replace -fuse-ld=gold with -fuse-ld=bfd, it works. The crti.o is still preferred over Scrti.o. This started to happen once glibc is updated. The difference is start.S in glibc has changed to use so called MOVL macro. It is defined in glibc's sysdep.h. /* Load an immediate into R. Note R is a register number and not a register name. */ #ifdef __LP64__ # define MOVL(R, NAME) \ movz PTR_REG (R), #:abs_g3:NAME; \ movk PTR_REG (R), #:abs_g2_nc:NAME; \ movk PTR_REG (R), #:abs_g1_nc:NAME; \ movk PTR_REG (R), #:abs_g0_nc:NAME; #else # define MOVL(R, NAME) \ movz PTR_REG (R), #:abs_g1:NAME; \ movk PTR_REG (R), #:abs_g0_nc:NAME; #endif The start.S has a code like MOVL(0, main), and after linking, 0 is assigned to x0. That code is only for non-PIC/PIE. Also, if main is in the .o file rather than in the .so file, both linkers had no problem: $ gcc -fPIC -o foo.o -c foo.c $ gcc -shared -o libfoo.so foo.o $ gcc -o main.o -c main.c $ gcc -fuse-ld=gold -o a.out -lfoo -L$PWD -Wl,-v,-rpath=$PWD main.o collect2 version 4.8.5 20150623 (Red Hat 4.8.5-28.0.4) /usr/bin/ld.gold --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -o a.out /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/crtbegin.o -L/home/aion1223/shared2 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../.. -lfoo -v -rpath=/home/aion1223/shared2 main.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/aarch64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crtn.o GNU gold (version 2.27-28.base.0.2.el7_5.1) 1.12 $ ./a.out 1 $ gcc -fuse-ld=bfd -o a.out -lfoo -L$PWD -Wl,-v,-rpath=$PWD main.o collect2 version 4.8.5 20150623 (Red Hat 4.8.5-28.0.4) /usr/bin/ld.bfd --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -o a.out /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/crtbegin.o -L/home/aion1223/shared2 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../.. -lfoo -v -rpath=/home/aion1223/shared2 main.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/aarch64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/crtn.o GNU ld version 2.27-28.base.0.2.el7_5.1 $ ./a.out 1 I am not sure if this is a Gold bug. However, I believe that it is worthy looking into. As this issue is not reproducible with bfd, I filed this bug against Gold. The details is here: https://github.com/golang/go/issues/28334 I haven't heard a single C/C++ application that puts main in a shared library yet. However, it seems like Go might do it more often. Perhaps, this bug might not be crucial in the C/C++ world but has some meaning in the Go world. -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils