Opened 12 years ago

Closed 9 years ago

#2458 closed bug (fixed)

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 Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

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 (2)

2458-unix.dpatch (1.4 KB) - added by batterseapower 9 years ago.
2458-base.dpatch (1.2 KB) - added by batterseapower 9 years ago.

Download all attachments as: .zip

Change History (16)

comment:1 Changed 11 years ago by igloo

difficulty: Unknown
Milestone: 6.10.1
Owner: set to igloo

comment:2 Changed 11 years ago by igloo

Resolution: fixed
Status: newclosed

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.

comment:3 Changed 10 years ago by mafo

Cc: fontaine@… added
Resolution: fixed
Status: closedreopened
Summary: GHC MacOS X Leopard build succeeds, but ghci complains about: unknown symbol `_environ'Unknown symbol `_environ' on MacOS X
Type of failure: None/Unknown
Version: 6.96.10.1

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.

comment:4 Changed 10 years ago by igloo

Milestone: 6.10.16.12.2
Owner: igloo deleted
Status: reopenednew

comment:5 Changed 10 years ago by igloo

Milestone: 6.12.26.12.3

comment:6 Changed 10 years ago by PHO

Cc: pho@… added

comment:7 Changed 10 years ago by igloo

Milestone: 6.12.36.14.1
Priority: normalhigh
[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()?

comment:8 Changed 9 years ago by igloo

Status: newinfoneeded

Can someone attach a small testcase for this bug please?

comment:9 Changed 9 years ago by igloo

Milestone: 7.0.17.0.2

comment:10 Changed 9 years ago by igloo

Milestone: 7.0.27.2.1

Changed 9 years ago by batterseapower

Attachment: 2458-unix.dpatch added

Changed 9 years ago by batterseapower

Attachment: 2458-base.dpatch added

comment:11 Changed 9 years ago by batterseapower

Status: infoneededpatch

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.

comment:12 Changed 9 years ago by batterseapower

Type of failure: None/UnknownGHC rejects valid program

comment:13 Changed 9 years ago by simonmar

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

comment:14 Changed 9 years ago by batterseapower

Resolution: fixed
Status: patchclosed

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.