following testcase causes gpf on i386. $ cat exe.c extern void f() __attribute__((weak,visibility("hidden"))); extern int puts( char const* ); int main() { f ? f() : puts( "f == null, skipped." ); return 0; } $ gcc exe.c -fPIE --save-temps -m32 -O1 && ./a.out Segmentation fault this fails on i386 with gcc 3.4.5, 4.0, 4.1 and 4.2 (4.3 not tested). x86_64 and ppc works fine, so it looks like a ix86 target bug.
btw, imho the weak+hidden is not a valid combination. such symbol can't be resolved in runtime because it doesn't exist in elf rel.plt/rel.dyn tables. it can be resolved only during linking several objects into one piece (e.g. exec/shlib), but in such case the weak+hidden behaves like plain hidden.
f always will bind local ... Also you should be using -PIE when linking.
(In reply to comment #2) > Also you should be using -PIE when linking. hmm, it doesn't work with int main(); $ gcc -s main.c -fpie -Wl,-pie /usr/bin/ld: /usr/lib64/crt1.o: relocation R_X86_64_32S against `__libc_csu_fini' can not be used when making a shared object; recompile with -fPIC /usr/lib64/crt1.o: could not read symbols: Bad value collect2: ld returned 1 exit status huh, glibc bug, linker bug?
(In reply to comment #2) > f always will bind local ... so, should gcc reject weak attribute in this (hidden visibility) case?
(In reply to comment #3) > (In reply to comment #2) > > > Also you should be using -PIE when linking. > > hmm, it doesn't work with int main(); > > $ gcc -s main.c -fpie -Wl,-pie > /usr/bin/ld: /usr/lib64/crt1.o: relocation R_X86_64_32S against > `__libc_csu_fini' can not be used when making a shared object; > recompile with -fPIC > /usr/lib64/crt1.o: could not read symbols: Bad value > collect2: ld returned 1 exit status > > huh, glibc bug, linker bug? with gcc-4.2.3 and binutils-2.18.50.0.4 it links fine.
Weak and hidden aren't really compatible. Linker should enforce it. I opened a linker bug: http://sourceware.org/bugzilla/show_bug.cgi?id=5789 As for gcc, I think it is OK since it is a user error and linker should issue an error. Besides, gcc doesn't know if the .o file will be used for PIE/shared library or normal executable. The runtime error only happens with PIE/shared library, not normal executable.
It is a compiler bug after all. From: http://groups.google.com/group/generic-abi/browse_thread/thread/4364eb484397ebe0 A hidden symbol must be defined in the same component, *if it is defined at all*. That last part is the key to the issue. In the case of a WEAK HIDDEN UNDEF symbol, it is possible for the symbol to remain undefined (or, looked at another way, it is possible for the symbol to be defined at link time as an absolute symbol with value 0). I agree with Daniel; the compiler should be aware of this possibility and generate code that will not require a dynamic relocation for this case. For a weak and hidden symbol, it is bound local only if PIC is false or it is used for branch. Otherwise, it should be treated with default visibility.
What's the status of this bug ? The same things can happen in libraries with fpic
(In reply to comment #8) > What's the status of this bug ? we currently still end up with call 0 on e.g. i386 > The same things can happen in libraries with fpic yes. Thing is that we could theoretically work around it by explicitly looking at the addr ¹) but that's just plain disgusting imho. And the hardened guys will not like the idea to drop DOPIC (i.e. build members of .a without PIC). So.. What's the status of that bug? Current binutils-2.20 and somewhat current gcc basically generate "wrong" code, or at least code that behaves in an unpleasant way causing grief.. ¹) https://bugs.uClibc.org/1033 thanks and cheers,
Well, simply re-ordering the visibility and the weak check in varasm.c:default_binds_local_p_1 should do the trick.
(In reply to comment #10) > Well, simply re-ordering the visibility and the weak check in > varasm.c:default_binds_local_p_1 should do the trick. > It does. http://gcc.gnu.org/ml/gcc-patches/2010-03/msg00665.html
whats the status on this bug? It still happens on gcc-4.4.4.
Created attachment 27716 [details] testcase This was (accidentally) fixed on for at least 4.7 ff but without adding a testcase like the attached.
(In reply to comment #13) > This was (accidentally) fixed on for at least 4.7 ff but without adding a > testcase like the attached. Are you sure it's been fixed? The test case segfaults for me on x86_64-linux when compiled by 4.8-20120826, 4.7-20120825, or 4.6-20120810, with -O1 -m32 and -fPIC or -fPIE. Without -m32 it doesn't segfault.
A patch is posted at https://gcc.gnu.org/ml/gcc-patches/2015-02/msg00410.html
Author: rth Date: Fri Feb 13 04:52:45 2015 New Revision: 220674 URL: https://gcc.gnu.org/viewcvs?rev=220674&root=gcc&view=rev Log: PR rtl/32219 gcc/ * cgraphunit.c (cgraph_node::finalize_function): Set definition before notice_global_symbol. (varpool_node::finalize_decl): Likewise. * varasm.c (default_binds_local_p_2): Rename from default_binds_local_p_1, add weak_dominate argument. Use direct returns instead of assigning to local variable. Unify varpool and cgraph paths via symtab_node. Reject undef weak variables before testing visibility. Reorder tests for simplicity. (default_binds_local_p): Use default_binds_local_p_2. (default_binds_local_p_1): Likewise. (decl_binds_to_current_def_p): Unify varpool and cgraph paths via symtab_node. (default_elf_asm_output_external): Emit visibility when specified. gcc/testsuite/ * gcc.dg/visibility-22.c: New test. * gcc.dg/visibility-23.c: New test. * gcc.target/i386/pr32219-1.c: New test. * gcc.target/i386/pr32219-2.c: New test. * gcc.target/i386/pr32219-3.c: New test. * gcc.target/i386/pr32219-4.c: New test. * gcc.target/i386/pr32219-5.c: New test. * gcc.target/i386/pr32219-6.c: New test. * gcc.target/i386/pr32219-7.c: New test. * gcc.target/i386/pr32219-8.c: New test. * gcc.target/i386/pr64317.c: Expect GOTOFF, not GOT. Added: trunk/gcc/testsuite/gcc.dg/visibility-22.c trunk/gcc/testsuite/gcc.dg/visibility-23.c trunk/gcc/testsuite/gcc.target/i386/pr32219-1.c trunk/gcc/testsuite/gcc.target/i386/pr32219-2.c trunk/gcc/testsuite/gcc.target/i386/pr32219-3.c trunk/gcc/testsuite/gcc.target/i386/pr32219-4.c trunk/gcc/testsuite/gcc.target/i386/pr32219-5.c trunk/gcc/testsuite/gcc.target/i386/pr32219-6.c trunk/gcc/testsuite/gcc.target/i386/pr32219-7.c trunk/gcc/testsuite/gcc.target/i386/pr32219-8.c Modified: trunk/gcc/ChangeLog trunk/gcc/cgraphunit.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.target/i386/pr64317.c trunk/gcc/varasm.c
Fixed. Thanks for the work on this one, HJ.
The following error started with r220674 on powerpc64-linux when trying to build 447.dealII from CPU2006 with -m64. /usr/bin/ld: exceptions.o: In function `ExceptionBase::what() const': exceptions.cc:(.text+0xda0): unresolvable R_PPC64_TOC16_HA against `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@@GLIBCXX_3.4.21' /usr/bin/ld: exceptions.cc:(.text+0xdac): unresolvable R_PPC64_TOC16_LO against `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@@GLIBCXX_3.4.21' /usr/bin/ld: final link failed: Nonrepresentable section on output collect2: error: ld returned 1 exit status
(In reply to Pat Haugen from comment #18) > The following error started with r220674 on powerpc64-linux when trying to > build 447.dealII from CPU2006 with -m64. > > /usr/bin/ld: exceptions.o: In function `ExceptionBase::what() const': > exceptions.cc:(.text+0xda0): unresolvable R_PPC64_TOC16_HA against > `std::__cxx11::basic_string<char, std::char_traits<char>, > std::allocator<char> >::~basic_string()@@GLIBCXX_3.4.21' > /usr/bin/ld: exceptions.cc:(.text+0xdac): unresolvable R_PPC64_TOC16_LO > against `std::__cxx11::basic_string<char, std::char_traits<char>, > std::allocator<char> >::~basic_string()@@GLIBCXX_3.4.21' > /usr/bin/ld: final link failed: Nonrepresentable section on output > collect2: error: ld returned 1 exit status Can you try fix in PR 65074?
(In reply to H.J. Lu from comment #19) > > Can you try fix in PR 65074? Yes, that fixes the problem.