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