Segmentation fault in non-dynamically linked binaries?

austin seipp as at 0xff.ath.cx
Wed Jun 30 11:18:59 EDT 2010


This issue began manifesting in a lot of ways on my computer, not just
GHC (but with ocaml, etc..) I did an upgrade of all my libc6-* related
libraries, and the issue seems to have gone away (i.e. static linking
works perfectly fine.)

Sorry for the trouble

On Wed, Jun 16, 2010 at 11:22 AM, austin seipp <as at 0xff.ath.cx> wrote:
> Forwarding this to g-h-u for archival purposes and in case anybody
> else has ideas (should'a done this earlier.)
>
>
> ---------- Forwarded message ----------
> From: austin seipp <as at 0xff.ath.cx>
> Date: Wed, Jun 16, 2010 at 11:21 AM
> Subject: Re: Segmentation fault in non-dynamically linked binaries?
> To: Simon Marlow <marlowsd at gmail.com>
>
>
> Follow up:
>
> Both of my machines are running debian x86_64 linux, both with libc6
> version 2.11.2-1 (aka eglibc,) from debian sid. My work machine does
> not exhibit the same segfaulting behavior as my home machine.
>
> Debugging with the rts source available and watching setFullProgArgv
> go by does not help a lot - when stgCallocBytes is called with strlen
> as a parameter (to determine how much to allocate,) the code
> immediately crashes upon arrival into the first instruction of strlen,
> but the strange thing is *which* strlen it is jumping to.
>
> From a simple 'hello world' executable on my work machine, when
> disassembling setFullProgArgv we get this:
>
> ...
> 0x0000000000432a26 <setFullProgArgv+54>:        xor    %ebp,%ebp
> 0x0000000000432a28 <setFullProgArgv+56>:        nopl   0x0(%rax,%rax,1)
> 0x0000000000432a30 <setFullProgArgv+64>:        mov    (%r14,%rbp,1),%rdi
> 0x0000000000432a34 <setFullProgArgv+68>:        mov    %rbp,%rbx
> 0x0000000000432a37 <setFullProgArgv+71>:        add
> 0x247f5a(%rip),%rbx        # 0x67a998 <full_prog_argv>
> 0x0000000000432a3e <setFullProgArgv+78>:        add    $0x1,%r12d
> 0x0000000000432a42 <setFullProgArgv+82>:        callq  0x4028b8 <strlen at plt>
> 0x0000000000432a47 <setFullProgArgv+87>:        lea    0x1(%rax),%edi
> 0x0000000000432a4a <setFullProgArgv+90>:        mov    $0x4616fe,%esi
> 0x0000000000432a4f <setFullProgArgv+95>:        callq  0x434790 <stgMallocBytes>
> 0x0000000000432a54 <setFullProgArgv+100>:       mov    %rax,(%rbx)
> 0x0000000000432a57 <setFullProgArgv+103>:       mov    0x247f3a(%rip),%rax
> ...
>
> Note that it calls strlen at plt which jumps to libc's implementation of strlen.
>
> However, when looking at this same program compiled on my home
> machine, we instead get:
>
> ...
> 0x0000000000432db6 <+54>:       xor    %ebp,%ebp
> 0x0000000000432db8 <+56>:       nopl   0x0(%rax,%rax,1)
> 0x0000000000432dc0 <+64>:       mov    (%r14,%rbp,1),%rdi
> 0x0000000000432dc4 <+68>:       mov    %rbp,%rbx
> 0x0000000000432dc7 <+71>:       add    0x24898a(%rip),%rbx        # 0x67b758
> <full_prog_argv>
> 0x0000000000432dce <+78>:       add    $0x1,%r12d
> 0x0000000000432dd2 <+82>:       callq  0x67b3c0 <strlen@@GLIBC_2.2.5>
> 0x0000000000432dd7 <+87>:       lea    0x1(%rax),%edi
> 0x0000000000432dda <+90>:       mov    $0x46207e,%esi
> 0x0000000000432ddf <+95>:       callq  0x434cb0 <stgMallocBytes>
> 0x0000000000432de4 <+100>:      mov    %rax,(%rbx)
> 0x0000000000432de7 <+103>:      mov    0x24896a(%rip),%rax        #
> 0x67b758 <full_prog_argv>
> ...
>
> Here we call a version of strlen which the dynamic linker enforces
> come from glibc v2.2.5. If we run objdump -x, we get:
>
> ...
> Version References:
>  required from librt.so.1:
>    0x09691973 0x00 04 GLIBC_2.3.3
>  required from libm.so.6:
>    0x09691a75 0x00 03 GLIBC_2.2.5
>  required from libc.so.6:
>    0x0d696913 0x00 05 GLIBC_2.3
>    0x09691a75 0x00 02 GLIBC_2.2.5
> ...
>
> So there are some dependencies on older GLIBC versions for certain
> symbols, but I'm not sure why.
>
> I'm at work agaom so I'll follow up again here in a few hours once I
> get back home after doing some more reading.
>
> On Tue, Jun 15, 2010 at 3:43 PM, austin seipp <as at 0xff.ath.cx> wrote:
>> Simon,
>>
>> Thanks for the reply.
>>
>> One interesting thing to note is that on my work machine, also running
>> x86_64 debian, with with a full update from apt (many updates come
>> from sid, others are from lenny,) static and dynamic linking both seem
>> to work fine for the same versions of GHC that affect my home machine.
>>
>> On my debian machine here at work I have a libc6 which is installed
>> from the unstable sid repository. It is libc6 version '2.11-1', which
>> is actually a version of eglibc, not glibc (although eglibc is
>> designed for full ABI-level compatibility - debian switched to it a
>> while ago.) I believe my home machine with x86_64 debian has the exact
>> same version of libc6 installed out of sid repos but I cannot confirm
>> that at the moment.
>>
>> I do not currently have access to my home machine from here. When I do
>> I'll get a copy of the 6.12.1 source code and do a debug link and do
>> some more investigation.
>>
>> Thanks,
>>
>> On Tue, Jun 15, 2010 at 5:33 AM, Simon Marlow <marlowsd at gmail.com> wrote:
>>> On 13/06/2010 07:26, austin seipp wrote:
>>>>
>>>> Hello,
>>>>
>>>> I am running GHC on x86_64 debian linux, and recently I have
>>>> discovered that the executables generated by my GHC segfault when the
>>>> linking step is not dynamic.
>>>> I discovered this while attempting to install haskell-src-exts, which
>>>> requires a linked version of Setup.hs when cabal builds it (and which
>>>> would fail inexplicably until I did
>>>> further investigation.)
>>>>
>>>> Example:
>>>>
>>>> link ~/t » cat hi.hs
>>>> main :: IO ()
>>>> main = putStrLn "hi"
>>>> link ~/t » ghc -dynamic hi.hs
>>>> link ~/t » file ./a.out
>>>> ./a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
>>>> dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not
>>>> stripped
>>>> link ~/t » ldd ./a.out
>>>>        linux-vdso.so.1 =>   (0x00007fffbadff000)
>>>>        libHShaskell98-1.0.1.1-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/haskell98-1.0.1.1/libHShaskell98-1.0.1.1-ghc6.12.3.so
>>>> (0x00007fab3a4c4000)
>>>>        libHSrandom-1.0.0.2-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/random-1.0.0.2/libHSrandom-1.0.0.2-ghc6.12.3.so
>>>> (0x00007fab3a2af000)
>>>>        libHStime-1.1.4-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/time-1.1.4/libHStime-1.1.4-ghc6.12.3.so
>>>> (0x00007fab39fad000)
>>>>        libHSprocess-1.0.1.3-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/process-1.0.1.3/libHSprocess-1.0.1.3-ghc6.12.3.so
>>>> (0x00007fab39d93000)
>>>>        libHSdirectory-1.0.1.1-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/directory-1.0.1.1/libHSdirectory-1.0.1.1-ghc6.12.3.so
>>>> (0x00007fab39b77000)
>>>>        libHSunix-2.4.0.2-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/unix-2.4.0.2/libHSunix-2.4.0.2-ghc6.12.3.so
>>>> (0x00007fab398c6000)
>>>>        librt.so.1 =>  /lib/librt.so.1 (0x00007fab396a2000)
>>>>        libutil.so.1 =>  /lib/libutil.so.1 (0x00007fab3949f000)
>>>>        libdl.so.2 =>  /lib/libdl.so.2 (0x00007fab3929b000)
>>>>        libHSold-time-1.0.0.5-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/old-time-1.0.0.5/libHSold-time-1.0.0.5-ghc6.12.3.so
>>>> (0x00007fab3903c000)
>>>>        libHSold-locale-1.0.0.2-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/old-locale-1.0.0.2/libHSold-locale-1.0.0.2-ghc6.12.3.so
>>>> (0x00007fab38e28000)
>>>>        libHSfilepath-1.1.0.4-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/filepath-1.1.0.4/libHSfilepath-1.1.0.4-ghc6.12.3.so
>>>> (0x00007fab38c07000)
>>>>        libHSarray-0.3.0.1-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/array-0.3.0.1/libHSarray-0.3.0.1-ghc6.12.3.so
>>>> (0x00007fab38992000)
>>>>        libHSbase-4.2.0.2-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/base-4.2.0.2/libHSbase-4.2.0.2-ghc6.12.3.so
>>>> (0x00007fab381f2000)
>>>>        libHSinteger-gmp-0.2.0.1-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/integer-gmp-0.2.0.1/libHSinteger-gmp-0.2.0.1-ghc6.12.3.so
>>>> (0x00007fab37fe1000)
>>>>        libgmp.so.3 =>  /usr/lib/libgmp.so.3 (0x00007fab37da1000)
>>>>        libHSghc-prim-0.2.0.0-ghc6.12.3.so =>
>>>>
>>>> /usr/local/lib/ghc-6.12.3/ghc-prim-0.2.0.0/libHSghc-prim-0.2.0.0-ghc6.12.3.so
>>>> (0x00007fab37b1c000)
>>>>        libHSrts-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/libHSrts-ghc6.12.3.so (0x00007fab378ba000)
>>>>        libm.so.6 =>  /lib/libm.so.6 (0x00007fab37637000)
>>>>        libHSffi-ghc6.12.3.so =>
>>>> /usr/local/lib/ghc-6.12.3/libHSffi-ghc6.12.3.so (0x00007fab3742a000)
>>>>        libc.so.6 =>  /lib/libc.so.6 (0x00007fab370c9000)
>>>>        libpthread.so.0 =>  /lib/libpthread.so.0 (0x00007fab36eac000)
>>>>        /lib64/ld-linux-x86-64.so.2 (0x00007fab3a6cb000)
>>>> link ~/t » ./a.out
>>>> hi
>>>> link ~/t » rm ./a.out *.hi *.o
>>>> link ~/t » ghc hi.hs
>>>> link ~/t » file ./a.out
>>>> ./a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
>>>> dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not
>>>> stripped
>>>> link ~/t » ldd ./a.out
>>>>        linux-vdso.so.1 =>   (0x00007fffaafff000)
>>>>        librt.so.1 =>  /lib/librt.so.1 (0x00007fdf83d77000)
>>>>        libutil.so.1 =>  /lib/libutil.so.1 (0x00007fdf83b74000)
>>>>        libdl.so.2 =>  /lib/libdl.so.2 (0x00007fdf8396f000)
>>>>        libgmp.so.3 =>  /usr/lib/libgmp.so.3 (0x00007fdf83730000)
>>>>        libm.so.6 =>  /lib/libm.so.6 (0x00007fdf834ae000)
>>>>        libc.so.6 =>  /lib/libc.so.6 (0x00007fdf8314c000)
>>>>        libpthread.so.0 =>  /lib/libpthread.so.0 (0x00007fdf82f30000)
>>>>        /lib64/ld-linux-x86-64.so.2 (0x00007fdf83f9c000)
>>>> link ~/t » ./a.out
>>>> [1]    7850 segmentation fault  ./a.out
>>>> link ~/t » gdb7.0 ./a.out
>>>>
>>>>
>>>>                                                       139 ↵
>>>> GNU gdb (GDB) 7.0
>>>> Copyright (C) 2009 Free Software Foundation, Inc.
>>>> License GPLv3+: GNU GPL version 3 or
>>>> later<http://gnu.org/licenses/gpl.html>
>>>> This is free software: you are free to change and redistribute it.
>>>> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
>>>> and "show warranty" for details.
>>>> This GDB was configured as "x86_64-unknown-linux-gnu".
>>>> For bug reporting instructions, please see:
>>>> <http://www.gnu.org/software/gdb/bugs/>...
>>>> Reading symbols from /home/a/t/a.out...done.
>>>> (gdb) r
>>>> Starting program: /home/a/t/a.out
>>>> [Thread debugging using libthread_db enabled]
>>>>
>>>> Program received signal SIGSEGV, Segmentation fault.
>>>> 0x000000000067b3c0 in strlen@@GLIBC_2.2.5 ()
>>>> (gdb) bt
>>>> #0  0x000000000067b3c0 in strlen@@GLIBC_2.2.5 ()
>>>> #1  0x0000000000432dd7 in setFullProgArgv ()
>>>> #2  0x000000000043464d in hs_init ()
>>>> #3  0x000000000043478d in startupHaskell ()
>>>> #4  0x0000000000433d59 in real_main ()
>>>> #5  0x0000000000433e87 in hs_main ()
>>>> #6  0x00007ffff6fccc4d in __libc_start_main () from /lib/libc.so.6
>>>> #7  0x0000000000402d49 in _start ()
>>>> (gdb)
>>>>
>>>>
>>>> What's interesting is that this occurs with all versions of GHC on my
>>>> machine, which include:
>>>>  * GHC 6.12.1
>>>>  * GHC 6.12.3
>>>>  * GHC 6.13.20100426
>>>>
>>>> Executables that were statically linked with GHC before this strange
>>>> behavior started occurring appear to still work, i.e. xmonad&  xmobar.
>>>> I recently did an update of my machine with aptitude, but I would not
>>>> think this would interfere with GHC.
>>>
>>> Strange - I suspect there is some ABI change in glibc that means the static
>>> libraries are no longer compatible with the new version.  You'll get more
>>> information out of gdb if you compile with -debug, then try stepping through
>>> from setFullProgArgv to see what goes wrong.
>>>
>>> If there is an ABI change, and it's going to appear in all the major Linux
>>> distros at some point, this could give us some difficulties with binary
>>> distributions.
>>>
>>> Cheers,
>>>        Simon
>>>
>>
>>
>>
>> --
>> - Austin
>>
>
>
>
> --
> - Austin
>
>
>
> --
> - Austin
>



-- 
- Austin


More information about the Glasgow-haskell-users mailing list