Ticket #2458 (closed bug: fixed)

Opened 4 years ago

Last modified 10 months ago

Unknown symbol `_environ' on MacOS X

Reported by: IgorBoehm Owned by:
Priority: high Milestone: 7.2.1
Component: libraries/base Version: 6.10.1
Keywords: environ Cc: igor@…, fontaine@…, pho@…
Operating System: MacOS X Architecture: x86
Type of failure: GHC rejects valid program Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Shared libraries and bundles on MacOS X Leopard don't have direct access to environ (i.e. extern char **environ), which is only available to the loader ld when a complete program is being linked. If direct access to environ is needed, the _NSGetEnviron() routine, defined in <crt_externs.h> can be used to retrieve the address of environ at runtime ( man environ(7) see last paragraph in section PROGRAMMING).

Two Libraries are affected by this - namely  base and  unix. Both of these Libraries implement (duplicate code) access to environ:

  •  base/include/HsBase.h:
    * ToDo: write a feature test that doesn't assume 'environ' to
    *    be in scope at link-time. */
    extern char** environ;
    INLINE char **__hscore_environ() { return environ; }
    
  •  unix/include/HsUnix.h
    extern char **environ;
    

Unfortunately this does not work on MaxOS X Leopard with XCode 3.0. My temporary workaround was to comment out the current definition of environ in the header files and add the following instead:

  • Hack for  base/include/HsBase.h:
    /* ToDo: write a feature test that doesn't assume 'environ' to
     *    be in scope at link-time. */
    //extern char **environ;
    //INLINE char **__hscore_environ() { return environ; }
    #include <crt_externs.h>
    INLINE char **__hscore_environ(void) { return (*_NSGetEnviron()); }
    
  • Hack for  unix/include/HsUnix.h:
    //extern char **environ;
    #include <crt_externs.h>
    INLINE char **__hsunix_environ (void) { return (*_NSGetEnviron()); }
    
  • Hack for  unix/System/Posix/Env.hsc:
    --getEnvironmentPrim :: IO [String]
    --getEnvironmentPrim = do
    --  c_environ <- peek c_environ_p
    --  arr <- peekArray0 nullPtr c_environ
    --  mapM peekCString arr
    --
    --foreign import ccall unsafe "&environ"
    --    c_environ_p :: Ptr (Ptr CString)
    getEnvironmentPrim :: IO [String]
    getEnvironmentPrim = do
      c_environ <- c_environ_p
      arr <- peekArray0 nullPtr c_environ
      mapM peekCString arr
    
    foreign import ccall unsafe "__hsunix_environ"
      c_environ_p :: IO (Ptr CString)
    

Unfortunately I do not know GHC well enough to propose a clean patch. With these 'hacks' ghc compiled from source on MacOS X Leopard with XCode 3.0 works well. It would also probably be good to get rid of the code duplication in the base and unix libraries.

Shall I open another Ticket for libraries/unix?

References:

Attachments

2458-unix.dpatch Download (1.4 KB) - added by batterseapower 10 months ago.
2458-base.dpatch Download (1.2 KB) - added by batterseapower 10 months ago.

Change History

Changed 3 years ago by igloo

  • owner set to igloo
  • difficulty set to Unknown
  • milestone set to 6.10.1

Changed 3 years ago by igloo

  • status changed from new to closed
  • resolution set to fixed

Hmm, this works for me; presumably fixed by Cabal's Distribution.Simple.GHC.stripExe doing:

    args = path : case buildOS of
       OSX -> ["-x"] -- By default, stripping the ghc binary on at least
                     -- some OS X installations causes:
                     --     HSbase-3.0.o: unknown symbol `_environ'"
                     -- The -x flag fixes that.
       _   -> []

so I'm closing this ticket. Please reopen it if you still think there's a problem.

Changed 2 years ago by mafo

  • status changed from closed to reopened
  • cc fontaine@… added
  • summary changed from GHC MacOS X Leopard build succeeds, but ghci complains about: unknown symbol `_environ' to Unknown symbol `_environ' on MacOS X
  • failure set to None/Unknown
  • version changed from 6.9 to 6.10.1
  • resolution fixed deleted

This bug also shows up with Haskell-created libraries.

If the executable which uses the library has been stripped the error occurs. If the executable has not been stripped the library can be loaded.

Changed 2 years ago by igloo

  • owner igloo deleted
  • status changed from reopened to new
  • milestone changed from 6.10.1 to 6.12.2

Changed 22 months ago by igloo

  • milestone changed from 6.12.2 to 6.12.3

Changed 21 months ago by PHO

  • cc pho@… added

Changed 20 months ago by igloo

  • priority changed from normal to high
  • milestone changed from 6.12.3 to 6.14.1
[20:55] < safiire> Has anyone here ran into a problem of trying to link a 
                   library compiled with ghc -c into a C++ project and 
                   receiving an unresolved symbol _environ.  I am aware that 
                   _environ is supposed to be defined in crt1.o, however the 
                   C++ project I am building is an audio unit plugin on OSX, so 
                   it never links against crt1.o as it is not an executable, 
                   but a shared object itself.  There is something called the 
                   osx _environ bug which is the cause of t
[20:55] < safiire> his.  The work around is that OSX applications are not 
                   supposed to call environ(), but are supposed to call 
                   _NSGetEnviron(), or, that is the workaround at least.  
                   HSBase4.2.0.0.a does not do this on OSX apparently.  Does 
                   anyone know how I can get my linker resolve this symbol, or 
                   not care that it is undefined, short of recompling haskel 
                   from source and manually patching it to not call environ()?

Changed 18 months ago by igloo

  • status changed from new to infoneeded

Can someone attach a small testcase for this bug please?

Changed 14 months ago by igloo

  • milestone changed from 7.0.1 to 7.0.2

Changed 11 months ago by igloo

  • milestone changed from 7.0.2 to 7.2.1

Changed 10 months ago by batterseapower

Changed 10 months ago by batterseapower

Changed 10 months ago by batterseapower

  • status changed from infoneeded to patch

I've attached some versions of the patch that use CPP to do the right thing on OS X.

I also don't know how to tickle the bug, but the docs do say that you shouldn't be using environ from a shared library, so I'd be tempted to apply these patches just for safety's sake.

Changed 10 months ago by batterseapower

  • failure changed from None/Unknown to GHC rejects valid program

Changed 10 months ago by simonmar

I don't know either. If this doesn't break anything, go ahead and commit.

Changed 10 months ago by batterseapower

  • status changed from patch to closed
  • resolution set to fixed

Fixed by:

commit 47ac5d859493ae0cd8dd02e1b4848f993acc3d5c
Author: Max Bolingbroke <batterseapower@hotmail.com>
Date:   Wed Apr 6 07:57:40 2011 +0100

    Use _NSGetEnviron on OS X: fixes #2458
commit a8d4731456ac3da0a70399e4ab821a763a4c04fb
Author: Max Bolingbroke <batterseapower@hotmail.com>
Date:   Wed Apr 6 07:57:21 2011 +0100

    Use _NSGetEnviron on OS X: fixes #2458
Note: See TracTickets for help on using tickets.