Bug 32219 - optimizer causes wrong code in pic/hidden/weak symbol checking.
Summary: optimizer causes wrong code in pic/hidden/weak symbol checking.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: patch
Depends on: 35513
Blocks:
  Show dependency treegraph
 
Reported: 2007-06-05 09:38 UTC by Pawel Sikora
Modified: 2021-09-22 07:03 UTC (History)
11 users (show)

See Also:
Host:
Target: i386-gnu-linux
Build:
Known to work: 4.1.2, 4.7.1
Known to fail: 4.6.1
Last reconfirmed: 2010-03-08 19:28:29


Attachments
testcase (1.06 KB, patch)
2012-06-28 22:49 UTC, Bernhard Reutner-Fischer
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Pawel Sikora 2007-06-05 09:38:03 UTC
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.
Comment 1 Pawel Sikora 2007-06-05 12:53:21 UTC
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.
Comment 2 Andrew Pinski 2007-06-05 13:30:28 UTC
f always will bind local ...
Also you should be using -PIE when linking.
Comment 3 Pawel Sikora 2007-06-05 14:10:02 UTC
(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?
Comment 4 Pawel Sikora 2007-06-05 14:13:14 UTC
(In reply to comment #2)
> f always will bind local ...

so, should gcc reject weak attribute in this (hidden visibility) case?
Comment 5 Pawel Sikora 2008-02-23 21:09:28 UTC
(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.
Comment 6 H.J. Lu 2008-02-23 23:12:05 UTC
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.
Comment 7 H.J. Lu 2008-02-25 22:16:17 UTC
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.
Comment 8 Matthieu CASTET 2009-12-29 23:20:04 UTC
What's the status of this bug ?
The same things can happen in libraries with fpic
Comment 9 Bernhard Reutner-Fischer 2010-03-08 19:28:29 UTC
(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,
Comment 10 Richard Biener 2010-03-09 12:39:46 UTC
Well, simply re-ordering the visibility and the weak check in varasm.c:default_binds_local_p_1 should do the trick.
Comment 11 Bernhard Reutner-Fischer 2010-03-16 13:35:19 UTC
(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
Comment 12 Natanael Copa 2010-06-30 11:52:50 UTC
whats the status on this bug? It still happens on gcc-4.4.4.
Comment 13 Bernhard Reutner-Fischer 2012-06-28 22:49:52 UTC
Created attachment 27716 [details]
testcase

This was (accidentally) fixed on for at least 4.7 ff but without adding a testcase like the attached.
Comment 14 Mikael Pettersson 2012-09-01 15:17:28 UTC
(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.
Comment 15 H.J. Lu 2015-02-06 16:24:25 UTC
A patch is posted at

https://gcc.gnu.org/ml/gcc-patches/2015-02/msg00410.html
Comment 16 Richard Henderson 2015-02-13 04:53:17 UTC
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
Comment 17 Richard Henderson 2015-02-13 04:58:33 UTC
Fixed.  Thanks for the work on this one, HJ.
Comment 18 Pat Haugen 2015-02-16 16:18:16 UTC
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
Comment 19 H.J. Lu 2015-02-16 17:06:24 UTC
(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?
Comment 20 Pat Haugen 2015-02-16 18:50:46 UTC
(In reply to H.J. Lu from comment #19)
> 
> Can you try fix in PR 65074?

Yes, that fixes the problem.