Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing '_environ' symbol used in libunix.a #5693

Closed
vicuna opened this issue Jul 20, 2012 · 12 comments
Closed

Missing '_environ' symbol used in libunix.a #5693

vicuna opened this issue Jul 20, 2012 · 12 comments

Comments

@vicuna
Copy link

vicuna commented Jul 20, 2012

Original bug ID: 5693
Reporter: thelema
Assigned to: @damiendoligez
Status: assigned (set by @damiendoligez on 2017-03-15T10:23:50Z)
Resolution: open
Priority: low
Severity: minor
Platform: x86_64
OS: OS X
OS Version: 10.7.4
Version: 3.12.1
Category: otherlibs

Bug description

When building a mixed OCaml/C library that includes unix.cmxa, the osx linker gives an error about an undefined symbol "_environ".

IRC Log: http://tunes.org/~nef/logs/ocaml/12.07.20 - starts at 07:02:49
Bug reporter cannot reproduce.

Steps to reproduce

When compiling a library as follows:
ocamlopt -o libocaml_rl_pi_rnn.so -I /usr/local/lib/ocaml/
-I /usr/local/lib/ocaml/site-lib/extlib -I
/usr/local/lib/ocaml/site-lib/batteries unix.cmxa nums.cmxa
batteries.cmxa rnnRL.cmxa ocaml_rl_pi_bi.ml -ccopt
ocaml_interface.c -ccopt -I/usr/local/lib/ocaml/ -ccopt
-shared

The following error happens.

Undefined symbols for architecture x86_64:
"_environ", referenced from:
_unix_execvpe in libunix.a(execvp.o)
_unix_environment in libunix.a(envir.o)

Additional information

10:17 < thelema> http://trac.macports.org/browser/trunk/dports/lang/hugs98/files/patch-packages-base-include-HsBase.h.diff?rev=81676
...
10:36 < [Joshuah]> its a bug in the unix code. i added the lines posted in the
link you gave me to unix.c and another .c file in
otherlibs/unix
10:36 < [Joshuah]> it now compiles and runs

The patch is:
-extern char** environ;
+#ifdef APPLE
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#else

  • extern char **environ;
    +#endif

File attachments

@vicuna
Copy link
Author

vicuna commented Jul 20, 2012

Comment author: @xavierleroy

Which version of XCode are you using?

As I said on caml-list, the "environ" variable is standard according to POSIX and Single Unix Specification, so something went terribly wrong here.

Damien, Xavier C.: can you reproduce on your Macs?

@vicuna
Copy link
Author

vicuna commented Jul 20, 2012

Comment author: @xavierleroy

More info posted by reporter on caml-list:

My setting is:

Mac OS X 10.7.4
gcc version: i686-apple-darwin11-llvm-gcc-4.2
ocaml 3.12.1
Xcode 4.3.3 (4E3002)

I don't develop in Xcode, but use makefiles instead. Homebrew was used to install ocaml.

The error only occurs when linking to a dynamic lib, not when I link against an executable (main loop in c).

@vicuna
Copy link
Author

vicuna commented Jul 20, 2012

Comment author: thelema

Per Benedikt Meurer on caml-list:

Of course... as stated in environ(7):

"Shared libraries and bundles don't have direct access to environ, which
is only available to the loader ld(1) when a complete program is being
linked. The environment routines can still be used, but 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 run-
time."

It has always been this way on OS X, so Keyan's patch is correct.

@vicuna
Copy link
Author

vicuna commented Jul 21, 2012

Comment author: @damiendoligez

That command line looks suspect to me:

  1. "-o libocaml_rl_pi_rnn.so": this tells ocamlopt to name its output file libocaml_rl_pi_rnn.so, but there is nothing to tell it that you want to build a shared library, so ocamlopt is going to make an executable and name it libocaml_rl_pi_rnn.so. This is probably not what you want. Note that you never get "undefined symbol" errors when building shared libraries.

  2. "-ccopt -shared":
    from gcc's man page:
    -shared
    Produce a shared object which can then be linked with other objects
    to form an executable. Not all systems support this option. For
    predictable results, you must also specify the same set of options
    that were used to generate code (-fpic, -fPIC, or model suboptions)
    when you specify this option.[1]

        This option is not supported on Mac OS X.
    

In any case, I cannot reproduce the bug as reported. When I do "ocamlopt -o foo.so unix.cmxa -ccopt -shared", I get errors, not only on _environ, but also on _caml_atom_table, _caml_code_area_start, and _caml_code_area_end.

I have uploaded an example that's almost working, but when I run a.out I get this error:
dlopen(./foo.so, 2): Symbol not found: _caml_atom_table
Referenced from: /Users/doligez/dynlink-example/foo.so
Expected in: flat namespace
in /Users/doligez/dynlink-example/foo.so

Xavier, can you tell us what's I'm missing?

@vicuna
Copy link
Author

vicuna commented Jul 23, 2012

Comment author: @damiendoligez

OK, what I was missing is the surprising semantics of COMMON data in C object files and its variations across C linkers...

We'll probably have a better fix in a future version of OCaml, but for now you need to reference a function from "startup.c", to prevent the Mac OS X linker from dropping the file when building your shared library.

See the new version of my example code (I've also fixed bar.c to avoid a segfault).

@vicuna
Copy link
Author

vicuna commented Jul 23, 2012

Comment author: @damiendoligez

Note for the future: the best solution we found so far is to add an initializer to every global variable of the runtime system, to force them into the data segment.
An other possibility: make the OCaml compiler output references to caml_atom_table as common rather than imported symbol.

@vicuna
Copy link
Author

vicuna commented Jul 27, 2012

Comment author: @damiendoligez

I have uploaded a more complete example that demonstrates passing arguments, returning values, and catching exceptions (dynlink-example3).

@xavierleroy
Copy link
Contributor

As of now, otherlibs/unix/execvp.c no longer references the environ global variable, but otherlibs/unix/envir.c still does and still does not contain the _NSGetEnviron dance suggested in the original report.

Do we still have a macOS problem here and should we do something about it? @damiendoligez

@vicuna vicuna added the bug label Mar 20, 2019
@damiendoligez
Copy link
Member

I don't think the problem is limited to environ.

IIRC, the problem is that an uninitialized global variable in C code is declared as COMMON in the object file, and the macos linker (unlike the linux linker) feels free to drop the object file when it is referenced only by this variable.

So our best bet so far is to have initializers for all of the runtime's global variables to avoid this COMMON nonsense.

Given the rarity of reports on this problem, this is not a priority.

@pmetzger
Copy link
Member

FWIW, I've never had a problem building on MacOS.

@github-actions
Copy link

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

@github-actions github-actions bot added the Stale label May 25, 2020
@xavierleroy
Copy link
Contributor

This issue has not be observed in a long time. It's not by lack of OCaml users who run macOS! So, I'm takign the liberty to close.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants