bug-binutils
[Top][All Lists]
Advanced

[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.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]