Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Copy relocation against protected symbol doesn't work #26579

Closed Quuxplusone closed 4 years ago

Quuxplusone commented 8 years ago
Bugzilla Link PR26580
Status RESOLVED WORKSFORME
Importance P normal
Reported by H.J. Lu (hjl.tools@gmail.com)
Reported on 2016-02-11 14:22:57 -0800
Last modified on 2020-02-09 22:03:35 -0800
Version trunk
Hardware PC Linux
CC costamagnagianfranco@yahoo.it, hfinkel@anl.gov, i@maskray.me, jrtc27@jrtc27.com, llvm-bugs@lists.llvm.org, octoploid@yandex.com, rafael@espindo.la, rengolin@gmail.com, robinlee.sysu@gmail.com, ryan@lovelett.me, sylvestre@debian.org
Fixed by commit(s)
Attachments run.sh (849 bytes, application/x-shellscript)
Blocks
Blocked by
See also
Protected data symbol means that it can't be pre-emptied.  It doesn't mean
its address won't be external.  This is true for pointer to protected
function.  With copy relocation, address of protected data defined in the
shared library may also be external.  We only know that for sure at run-time.
BFD linker refuses to create such binary.  But gold doesn't check it.

[hjl@gnu-6 pr65248]$ cat x.c
extern int a;

extern void bar (void);

int main()
{
  bar ();
  if (a != 30)
    __builtin_abort();
  return 0;
}
[hjl@gnu-6 pr65248]$ cat bar.c
int a;

__attribute__((visibility("protected"))) int a;

void
bar ()
{
  a = 30;
}
[hjl@gnu-6 pr65248]$ make y
/export/build/gnu/llvm-clang/build-x86_64-linux/bin/clang -O3   -c -o x.o x.c
/export/build/gnu/llvm-clang/build-x86_64-linux/bin/clang -O3 -fpic    -c -o
bar.o bar.c
/export/build/gnu/llvm-clang/build-x86_64-linux/bin/clang  -fuse-ld=gold -
shared -o libfoo.so bar.o
/export/build/gnu/llvm-clang/build-x86_64-linux/bin/clang  -fuse-ld=gold -o y
x.o libfoo.so -Wl,-R,.
[hjl@gnu-6 pr65248]$ ./y
Aborted
[hjl@gnu-6 pr65248]$ make x
/export/build/gnu/llvm-clang/build-x86_64-linux/bin/clang  -shared -o libbar.so
bar.o
/usr/local/bin/ld: bar.o: relocation R_X86_64_PC32 against protected symbol `a'
can not be used when making a shared object
/usr/local/bin/ld: final link failed: Bad value
clang-3.9: error: linker command failed with exit code 1 (use -v to see
invocation)
Makefile:58: recipe for target 'libbar.so' failed
make: *** [libbar.so] Error 1
[hjl@gnu-6 pr65248]$
Quuxplusone commented 8 years ago
This bug currently causes a Swift build failure on Linux:

Swift.o: relocation R_X86_64_PC32 against protected symbol
`_Tvs19_emptyStringStorageVs6UInt32' can not be used when making a shared object
ld.bfd: final link failed: Bad value

% ./swift-demangle _Tvs19_emptyStringStorageVs6UInt32
_Tvs19_emptyStringStorageVs6UInt32 ---> Swift._emptyStringStorage : Swift.UInt32
Quuxplusone commented 8 years ago
I can't reproduce the part about ld.bfd complaining. I have:
GNU ld version 2.25-15.fc23

I also get an abort when compiling with gcc (gcc (GCC) 5.3.1 20151207 (Red Hat
5.3.1-2)). Is the same bug present in gcc?
Quuxplusone commented 8 years ago
(In reply to comment #2)
> I can't reproduce the part about ld.bfd complaining. I have:
> GNU ld version 2.25-15.fc23
>
>
> I also get an abort when compiling with gcc (gcc (GCC) 5.3.1 20151207 (Red
> Hat 5.3.1-2)). Is the same bug present in gcc?

Please get binutils 2.26.
Quuxplusone commented 8 years ago

Attached run.sh (849 bytes, application/x-shellscript): test

Quuxplusone commented 8 years ago
(In reply to comment #3)
> (In reply to comment #2)
> > I can't reproduce the part about ld.bfd complaining. I have:
> > GNU ld version 2.25-15.fc23
> >
> >
> > I also get an abort when compiling with gcc (gcc (GCC) 5.3.1 20151207 (Red
> > Hat 5.3.1-2)). Is the same bug present in gcc?
>
> Please get binutils 2.26.

I can't reproduce even with trunk.

I have attached the exact script I am using. I get the same results with gcc
and clang: No warnings and ./t aborts.

The ld version is:
GNU ld (GNU Binutils) 2.26.51.20160212
Quuxplusone commented 8 years ago
(In reply to comment #5)
> (In reply to comment #3)
> > (In reply to comment #2)
> > > I can't reproduce the part about ld.bfd complaining. I have:
> > > GNU ld version 2.25-15.fc23
> > >
> > >
> > > I also get an abort when compiling with gcc (gcc (GCC) 5.3.1 20151207 (Red
> > > Hat 5.3.1-2)). Is the same bug present in gcc?
> >
> > Please get binutils 2.26.
>
> I can't reproduce even with trunk.
>
> I have attached the exact script I am using. I get the same results with gcc
> and clang: No warnings and ./t aborts.
>
> The ld version is:
> GNU ld (GNU Binutils) 2.26.51.20160212

GCC 5 above is fixed.  Please upload your bar.o compiled with -fPIC -O3 using
clang and GCC 5.
Quuxplusone commented 8 years ago

To get the correct run-time behavior, glibc with fix for

https://sourceware.org/bugzilla/show_bug.cgi?id=17711

is required.

Quuxplusone commented 8 years ago
> $CC -shared bar.o -o bar.so -fuse-ld=bfd

You have to make sure that the correct linker is used here.
Put it first in your $PATH, for example.
Quuxplusone commented 8 years ago
I have the same problem on Arch Linux:

GNU ld (GNU Binutils) 2.26.0.20160302
gcc version 5.3.0 (GCC)
Target: x86_64-unknown-linux-gnu

/usr/bin/ld: stdlib/public/core/linux/x86_64/Swift.o: relocation R_X86_64_PC32
against protected symbol `_TMPSa' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
Quuxplusone commented 8 years ago

Forgot to say, I'm using Clang ToT-ish at 266363.

Quuxplusone commented 6 years ago
I try to reproduce this issue on Fedora 29. The situation is changed.
I tested a clean Fedora 29 docker environment. All packages come from official
repo.

# rpm -q clang binutils gcc
clang-7.0.0-2.fc29.x86_64
binutils-2.31.1-13.fc29.x86_64
gcc-8.2.1-4.fc29.x86_64

Linking with bfd is done but running is aborted:

# make y
clang  -O3 -c -o x.o x.c
clang  -O3 -fpic    -c -o bar.o bar.c
clang  -fuse-ld=bfd -shared -o libfoo.so bar.o
clang  -fuse-ld=bfd -o y x.o libfoo.so -Wl,-R,.
[root@d44816330e72 clang-protected-link]# ./y
Aborted (core dumped)

Linking with gold is failed:
# make y
clang  -O3 -c -o x.o x.c
clang  -O3 -fpic    -c -o bar.o bar.c
clang  -fuse-ld=gold -shared -o libfoo.so bar.o
clang  -fuse-ld=gold -o y x.o libfoo.so -Wl,-R,.
/usr/bin/ld.gold: error: x.o: cannot make copy relocation for protected symbol
'a', defined in libfoo.so
clang-7: error: linker command failed with exit code 1 (use -v to see
invocation)
make: *** [Makefile:10: y] Error 1
Quuxplusone commented 6 years ago
(In reply to Robin Lee from comment #11)
> I try to reproduce this issue on Fedora 29. The situation is changed.
> I tested a clean Fedora 29 docker environment. All packages come from
> official repo.
>
> # rpm -q clang binutils gcc
> clang-7.0.0-2.fc29.x86_64
> binutils-2.31.1-13.fc29.x86_64
> gcc-8.2.1-4.fc29.x86_64
>
> Linking with bfd is done but running is aborted:
>
> # make y
> clang  -O3 -c -o x.o x.c
> clang  -O3 -fpic    -c -o bar.o bar.c

# readelf -r bar.o

Relocation section '.rela.text' at offset 0x120 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000002  000300000002 R_X86_64_PC32     0000000000000004 a - 8

Relocation section '.rela.eh_frame' at offset 0x138 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0

# objdump -d bar.o

bar.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <bar>:
   0:   c7 05 00 00 00 00 1e    movl   $0x1e,0x0(%rip)        # a <bar+0xa>
   7:   00 00 00
   a:   c3                      retq
Quuxplusone commented 6 years ago

Same on Debian using clang-7 packages from apt.llvm.org

Quuxplusone commented 6 years ago
(In reply to Robin Lee from comment #12)
> (In reply to Robin Lee from comment #11)
> > I try to reproduce this issue on Fedora 29. The situation is changed.
> > I tested a clean Fedora 29 docker environment. All packages come from
> > official repo.
> >
> > # rpm -q clang binutils gcc
> > clang-7.0.0-2.fc29.x86_64
> > binutils-2.31.1-13.fc29.x86_64
> > gcc-8.2.1-4.fc29.x86_64
> >
> > Linking with bfd is done but running is aborted:
> >
> > # make y
> > clang  -O3 -c -o x.o x.c
> > clang  -O3 -fpic    -c -o bar.o bar.c
>
> # readelf -r bar.o
>
> Relocation section '.rela.text' at offset 0x120 contains 1 entry:
>   Offset          Info           Type           Sym. Value    Sym. Name +
> Addend
> 000000000002  000300000002 R_X86_64_PC32     0000000000000004 a - 8
>
> Relocation section '.rela.eh_frame' at offset 0x138 contains 1 entry:
>   Offset          Info           Type           Sym. Value    Sym. Name +
> Addend
> 000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
>
> # objdump -d bar.o
>
> bar.o:     file format elf64-x86-64
>
>
> Disassembly of section .text:
>
> 0000000000000000 <bar>:
>    0: c7 05 00 00 00 00 1e    movl   $0x1e,0x0(%rip)        # a <bar+0xa>
>    7: 00 00 00
>    a: c3                      retq

GCC 8 generates:

[hjl@gnu-cfl-1 pr65248]$ objdump -dwr bar.o

bar.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <bar>:
   0:   48 8b 05 00 00 00 00    mov    0x0(%rip),%rax        # 7 <bar+0x7>  3: R_X86_64_REX_GOTPCRELX   a-0x4
   7:   c7 00 1e 00 00 00       movl   $0x1e,(%rax)
   d:   c3                      retq
[hjl@gnu-cfl-1 pr65248]$
Quuxplusone commented 6 years ago

What I found is the regression of ld.bfd. The issue with clang is still the same as previous.

Quuxplusone commented 6 years ago
(In reply to Robin Lee from comment #15)
> What I found is the regression of ld.bfd. The issue with clang is still the
> same as previous.

GCC, glibc and ld.bfd have been updated to cope with protected symbols.
Quuxplusone commented 6 years ago
(In reply to H.J. Lu from comment #16)
> (In reply to Robin Lee from comment #15)
> GCC, glibc and ld.bfd have been updated to cope with protected symbols.

I know that. But ld.bfd works as expected on Fedora 28 but breaks on Fedora 29.
Quuxplusone commented 5 years ago
Hello, I still get the same issue on Ubuntu i386 architecture.
The file seems to be miscompiled on clang, while gcc builds it just fine.

What is interesting is that bfd fails to link the libary, and ld is good.
So maybe this is a double bug, in this case please help me reporting it to
glib/binutils folks accordingly :)

$ echo '
extern int a;
extern void bar (void);
int main() {
  bar ();
  if (a != 30)
    __builtin_abort();
  return 0;
}' > x.c

echo 'int a;
__attribute__((visibility("protected"))) int a;
void bar () {
  a = 30;
}
' > bar.c

$ VERSION=7
$ clang-$VERSION -O3 -c -o x.o x.c
$ clang-$VERSION -O3 -fpic -c -o bar.o bar.c
$ clang-$VERSION -fuse-ld=bfd -shared -o libfoo.so bar.o
/usr/bin/ld.bfd: bar.o: relocation R_386_GOTOFF against protected data `a' can
not be used when making a shared object
/usr/bin/ld.bfd: final link failed: bad value
clang: error: linker command failed with exit code 1 (use -v to see invocation)

$ objdump -d bar.o

bar.o:     file format elf32-i386

Disassembly of section .text:

00000000 <bar>:
   0:   e8 00 00 00 00          call   5 <bar+0x5>
   5:   58                      pop    %eax
   6:   81 c0 03 00 00 00       add    $0x3,%eax
   c:   c7 80 00 00 00 00 1e    movl   $0x1e,0x0(%eax)
  13:   00 00 00
  16:   c3                      ret

$ readelf -r bar.o

Relocation section '.rel.text' at offset 0xe0 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000008  0000020a R_386_GOTPC       00000000   _GLOBAL_OFFSET_TABLE_
0000000e  00000309 R_386_GOTOFF      00000004   a

$ clang-$VERSION -fuse-ld=gold -shared -o libfoo.so bar.o
(this is ok)

$ gcc -v -shared -o libfoo.so bar.o
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/8/lto-wrapper
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 8.2.0-13ubuntu1'
--with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-
languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-
major-version-only --program-suffix=-8 --program-prefix=i686-linux-gnu- --
enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-
gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-
clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-
libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-
libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-
system-zlib --enable-objc-gc=auto --enable-targets=all --enable-multiarch --
disable-werror --with-arch-32=i686 --with-multilib-list=m32,m64,mx32 --enable-
multilib --with-tune=generic --enable-checking=release --build=i686-linux-gnu --
host=i686-linux-gnu --target=i686-linux-gnu
Thread model: posix
gcc version 8.2.0 (Ubuntu 8.2.0-13ubuntu1)
COMPILER_PATH=/usr/lib/gcc/i686-linux-gnu/8/:/usr/lib/gcc/i686-linux-gnu/8/:/usr/lib/gcc/i686-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/8/:/usr/lib/gcc/i686-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/8/:/usr/lib/gcc/i686-linux-gnu/8/../../../i386-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/8/../../../../lib/:/lib/i386-linux-gnu/:/lib/../lib/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/i686-linux-gnu/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'libfoo.so' '-mtune=generic' '-
march=i686'
 /usr/lib/gcc/i686-linux-gnu/8/collect2 -plugin /usr/lib/gcc/i686-linux-gnu/8/liblto_plugin.so -plugin-opt=/usr/lib/gcc/i686-linux-gnu/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccMVGMSP.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_i386 --hash-style=gnu --as-needed -shared -z relro -o libfoo.so /usr/lib/gcc/i686-linux-gnu/8/../../../i386-linux-gnu/crti.o /usr/lib/gcc/i686-linux-gnu/8/crtbeginS.o -L/usr/lib/gcc/i686-linux-gnu/8 -L/usr/lib/gcc/i686-linux-gnu/8/../../../i386-linux-gnu -L/usr/lib/gcc/i686-linux-gnu/8/../../../../lib -L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/i686-linux-gnu/8/../../.. bar.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/i686-linux-gnu/8/crtendS.o /usr/lib/gcc/i686-linux-gnu/8/../../../i386-linux-gnu/crtn.o
/usr/bin/ld: bar.o: relocation R_386_GOTOFF against protected data `a' can not
be used when making a shared object
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

$ gcc -O3 -fpic -c -o bar.o bar.c

$ readelf -r bar.o

Relocation section '.rel.text' at offset 0x1dc contains 3 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000001  00000b02 R_386_PC32        00000000   __x86.get_pc_thunk.ax
00000006  00000c0a R_386_GOTPC       00000000   _GLOBAL_OFFSET_TABLE_
0000000c  00000d2b R_386_GOT32X      00000004   a

Relocation section '.rel.eh_frame' at offset 0x1f4 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000020  00000202 R_386_PC32        00000000   .text
00000034  00000502 R_386_PC32        00000000   .text.__x86.get_pc_thu

$ objdump -d bar.o

bar.o:     file format elf32-i386

Disassembly of section .text:

00000000 <bar>:
   0:   e8 fc ff ff ff          call   1 <bar+0x1>
   5:   05 01 00 00 00          add    $0x1,%eax
   a:   8b 80 00 00 00 00       mov    0x0(%eax),%eax
  10:   c7 00 1e 00 00 00       movl   $0x1e,(%eax)
  16:   c3                      ret

Disassembly of section .text.__x86.get_pc_thunk.ax:

00000000 <__x86.get_pc_thunk.ax>:
   0:   8b 04 24                mov    (%esp),%eax
   3:   c3                      ret

$ clang-$VERSION -fuse-ld=bfd -shared -o libfoo.so bar.o
(with gcc compiling bar.c the bfd linker succeedes)
$ clang-$VERSION -fuse-ld=gold -shared -o libfoo.so bar.o
(with gcc compiling bar.c the gold linker succeedes)
Quuxplusone commented 5 years ago
(In reply to Gianfranco from comment #18)
> Hello, I still get the same issue on Ubuntu i386 architecture.
> The file seems to be miscompiled on clang, while gcc builds it just fine.
Which version of your ld's?
ld --version
ld.bfd --version
ld.gold --version

And which version of Ubuntu are you using?
Quuxplusone commented 5 years ago
(In reply to Robin Lee from comment #19)
> (In reply to Gianfranco from comment #18)
> > Hello, I still get the same issue on Ubuntu i386 architecture.
> > The file seems to be miscompiled on clang, while gcc builds it just fine.
> Which version of your ld's?
> ld --version
> ld.bfd --version
> ld.gold --version
>
> And which version of Ubuntu are you using?

The linker doesn't matter; LLVM produced wrong code. Glibc defines
DL_EXTERN_PROTECTED_DATA on all of aarch64, arm, i386, (nios2) and x86_64,
which means that, for all of those, LLVM must assume that protected symbols can
be subjected to copy relocations and therefore may be external. Specifically
for i386, this means we can't use @GOTOFF and have to do a full indirection via
the GOT.
Quuxplusone commented 5 years ago
# ld --version
GNU ld (GNU Binutils for Ubuntu) 2.31.1
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

# ld.bfd --version
GNU ld (GNU Binutils for Ubuntu) 2.31.1
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

# ld.gold --version
GNU gold (GNU Binutils for Ubuntu 2.31.1) 1.16
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
Quuxplusone commented 4 years ago
The original issue is "Copy relocation against protected symbol doesn't work".
I agree with Rich Felker (https://gcc.gnu.org/ml/gcc/2016-04/msg00168.html) and
Cary Coutant (https://sourceware.org/ml/binutils/2016-03/msg00407.html
https://gcc.gnu.org/ml/gcc/2016-04/msg00158.html
https://gcc.gnu.org/ml/gcc/2016-04/msg00169.html) that we should
keep using direct access against protected symbols and disallow copy
relocations against protected symbols.

I appreciate that Cary Coutant and Rafael Ávila de Espíndola added diagnostics
to gold and lld, respectively:

gold (https://sourceware.org/bugzilla/show_bug.cgi?id=19823)
lld (https://bugs.llvm.org/show_bug.cgi?id=31476)

And I hope the following resolutions could be reworked:

GCC 5 x86-64 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248)
i386 was flagged as a reproduce
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55012)

__attribute__((visibility("protected"))) int a;
int foo() { return a; } // GCC>=5 uses R_X86_64_GOTPCREL/R_X86_64_REX_GOTPCRELX
instead of R_X86_64_PC32
binutils 2.26: R_X86_64_PC32 can no longer be used against a protected symbol
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=ca3fe95e469b9daec153caa2c90665f5daaec2b5
Quuxplusone commented 4 years ago

GCC x86-64 issue can be nicely fixed with https://gcc.gnu.org/ml/gcc/2019-05/msg00215.html