http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46713

           Summary: -fvisibility=hidden generates broken code
           Product: gcc
           Version: 4.5.1
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: river+...@tamara.tcx.org.uk
              Host: i386-pc-solaris2.10
            Target: i386-pc-solaris2.10
             Build: i386-pc-solaris2.10


This seems to be identical to a previous problem report on gcc-help[0], which I
ran into recently.

hemlock% gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/ts/lib/gcc/i386-pc-solaris2.10/4.5.1/lto-wrapper
Target: i386-pc-solaris2.10
Configured with: .././configure --prefix=/opt/ts --bindir=/opt/ts/bin
--libdir=/opt/ts/lib --mandir=/opt/ts/share/man --datadir=/opt/ts/share
--includedir=/opt/ts/include --infodir=/opt/ts/share/info
--libexecdir=/opt/ts/lib --sysconfdir=/etc/opt/ts --enable-nls --disable-static
--with-gnu-as --with-as=/opt/ts/binutils/bin/as --with-gnu-ld
--with-ld=/opt/ts/binutils/bin/ld --enable-threads=posix --enable-shared
--enable-multilib --without-x --with-system-zlib
--enable-languages=c,c++,fortran,objc --with-mpfr=/opt/ts --with-gmp=/opt/ts
--with-pkgversion=Toolserver --with-local-prefix=/opt/ts
Thread model: posix
gcc version 4.5.1 (Toolserver) 

GNU assembler version 2.20.1 (i386-pc-solaris2.10) using BFD version (GNU
Binutils) 2.20.1.20100303
GNU ld (GNU Binutils) 2.20.1.20100303
also reproducible with: ld: Software Generation Utilities - Solaris Link
Editors: 5.10-1.500

SunOS hemlock 5.10 Generic_142910-17 i86pc i386 i86pc

Test case (test.c):

struct A;
typedef int (*F)(struct A*);
extern const struct A a;
struct A { F f; };
static int f(struct A* x) { return (x==&a); }
const struct A a = { f };

The problem is that when -fvisibility=hidden is used, GCC produces code which
is not accepted by the linker.  Removing -fvisibility=hidden fixes the problem.
 This is somewhat surprising since GCC claims -fvisibility=hidden is ignored;
so why does it make a difference?

hemlock% gcc -m64 -fPIC -O2 -shared test.c -o test               
hemlock% gcc -m64 -fPIC -O2 -shared test.c -o test -fvisibility=hidden
test.c:6:14: warning: visibility attribute not supported in this configuration;
ignored
/opt/ts/binutils/bin/ld: /var/tmp//ccezimpZ.o: relocation R_X86_64_PC32 against
symbol `a' can not be used when making a shared object; recompile with -fPIC
/opt/ts/binutils/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status

With GNU ld, the tested example works fine in 32-bit mode, but the problem
occurs in 64-bit mode (-m64).  With Sun ld, both 32- and 64-bit versions are
broken.

This is a diff of the working asm output, and the broken output (with
-fvisibility) in 64-bit mode:

hemlock% diff -u test.s.working test.s
--- test.s.working      2010-11-29 21:10:20.293575000 +0000
+++ test.s      2010-11-29 21:10:26.449154000 +0000
@@ -4,9 +4,10 @@
        .type   f, @function
 f:
 .LFB0:
-       xorl    %eax, %eax
-       cmpq    a...@gotpcrel(%rip), %rdi
+       leaq    a(%rip), %rax
+       cmpq    %rax, %rdi
        sete    %al
+       movzbl  %al, %eax
        ret
 .LFE0:
        .size   f, .-f

And the 32-bit diff:

hemlock% diff -u test.s.working test.s
--- test.s.working      2010-11-29 21:14:36.120019000 +0000
+++ test.s      2010-11-29 21:14:37.509620000 +0000
@@ -5,7 +5,7 @@
 f:
        call    .LPR2
        addl    $_GLOBAL_OFFSET_TABLE_, %ecx
-       movl    a...@got(%ecx), %eax
+       leal    a...@gotoff(%ecx), %eax
        cmpl    %eax, 4(%esp)
        sete    %al
        movzbl  %al, %eax

[0] http://gcc.gnu.org/ml/gcc-help/2008-02/msg00042.html

Reply via email to