
The difference is that libpthread depends on ld-linux.so as a shared object dependency (grep the readelf -Wa output for `NEEDED`) and ld-
#8935: Obscure linker bug leads to crash in GHCi -------------------------------------+------------------------------------ Reporter: simonmar | Owner: simonmar Type: bug | Status: new Priority: high | Milestone: 7.8.3 Component: Runtime System | Version: 7.8.1-rc2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: GHCi crash | Difficulty: Rocket Science Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by trommler): Replying to [comment:6 dagit]: linux.so defines a `LOCAL` symbol for environ. As I understand it, that means the dynamic linker thinks libpthread defines environ as `LOCAL` (so it goes to look for a different definition and ends up with the right one). For libgmp it looks in libc.so and finds a `WEAK` definition and uses it because there is no other `GLOBAL` definition.
To help demonstrate this, consider this example. On my system, libz.so
has dependencies similar to libgmp.so:
{{{ $ readelf -Wa /usr/lib64/libgmp.so.10 | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] $ readelf -Wa /usr/lib64/libz.so.1 | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] }}}
I'm still fuzzy on some of the details, but it seems that `WEAK` and `LOCAL` mean very different things to the dynamic linker. `WEAK` is the same as `GLOBAL` but the link priority is lower, while `LOCAL` means the symbol should not be exported. As far as I can tell, when it finds `LOCAL` it continues the search whereas with `WEAK` it stops earlier because technically it has found an exported symbol. I checked on openSUSE 13.1 (x86_64 and powerpc64) and I have the same {{{NEEDED}}} for libc.so.
{{{environ}}} is a {{{WEAK}}} symbol in my libc.so, too. Here is my libc.so.6 on powerpc64: {{{ 00000000001d7ce0 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d7d00 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d7ee8 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d7ef0 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d8018 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d84a0 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d84a8 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d84b0 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d8570 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d8928 0000056600000026 R_PPC64_ADDR64 00000000001da1f0 __environ + 0 00000000001d81e8 0000013100000026 R_PPC64_ADDR64 00000000001da1f0 _environ + 0 305: 00000000001da1f0 8 OBJECT WEAK DEFAULT 32 _environ@@GLIBC_2.3 1026: 00000000001da1f0 8 OBJECT WEAK DEFAULT 32 environ@@GLIBC_2.3 1382: 00000000001da1f0 8 OBJECT GLOBAL DEFAULT 32 __environ@@GLIBC_2.3 178: 00000000001d8fa8 8 OBJECT LOCAL DEFAULT 32 last_environ 2904: 00000000001c9628 1436 FUNC LOCAL DEFAULT 28 __add_to_environ 4138: 00000000001da1f0 8 OBJECT WEAK DEFAULT 32 _environ 4843: 00000000001da1f0 8 OBJECT GLOBAL DEFAULT 32 __environ 4957: 00000000001da1f0 8 OBJECT WEAK DEFAULT 32 environ }}} On x86_64 it looks similar to comment [comment:5] except the line with environ.c is missing. Do openSUSE patch their system linker? I'll go ask on their mailing list and report back. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8935#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler