[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug gold/23870] New: gold does not resolve the address of main when mai
From: |
stephen.kim at oracle dot com |
Subject: |
[Bug gold/23870] New: gold does not resolve the address of main when main is in a shared library |
Date: |
Wed, 07 Nov 2018 13:47:29 +0000 |
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 gold/23870] New: gold does not resolve the address of main when main is in a shared library,
stephen.kim at oracle dot com <=