diff mbox

[PR,63758] fix liblto_plugin.so undefined _environ reference on OSX host

Message ID CAB=4xhoAKmPvRCzJDoF3Sd_YyzTfc-dNWk-k3CCjvN2L0BURVQ@mail.gmail.com
State New
Headers show

Commit Message

Roland McGrath Nov. 6, 2014, 12:25 a.m. UTC
As I described in the bug, OSX (as documented) does not permit shared
libraries to refer directly to the environ global variable.  Instead, they
must call the function _NSGetEnviron to get the address of environ.  This
becomes a problem when some libiberty code that uses environ directly gets
linked into the liblto_plugin.so shared library.

On an OSX 10.7.5 system, any attempt to run gcc/g++ for a linking step
fails like this:

../bin/../lib/gcc/.../4.9.2/../../../../.../bin/ld:
.../bin/../libexec/gcc/.../4.9.2/liblto_plugin.so: error loading
plugin: dlopen(.../bin/../libexec/gcc/.../4.9.2/liblto_plugin.so, 2):
Symbol not found: _environ
  Referenced from: .../bin/../libexec/gcc/.../4.9.2/liblto_plugin.so
  Expected in: flat namespace
 in .../bin/../libexec/gcc/.../4.9.2/liblto_plugin.so
collect2:error: ld returned 1 exit status

On some difference OSX systems, it works fine.  I don't know why.  But it's
documented in OSX's environ(7) man page that shared libraries cannot refer
to environ directly.

This patch fixed it for me.  It's not very autoconfy, but it's simple and
it works.

OK for trunk and 4.9 branch?


Thanks,
Roland


libiberty/
2014-11-05  Roland McGrath  <mcgrathr@google.com>

	PR other/63758
	* environ.h: New file.
	* xmalloc.c: Include it.
	(xmalloc_failed): Don't declare environ directly here.
	* pex-unix.c: Likewise.


@@ -117,7 +118,6 @@ void
 xmalloc_failed (size_t size)
 {
 #ifdef HAVE_SBRK
-  extern char **environ;
   size_t allocated;

   if (first_break != NULL)

Comments

Mike Stump Nov. 6, 2014, 5:58 p.m. UTC | #1
On Nov 5, 2014, at 4:25 PM, Roland McGrath <mcgrathr@google.com> wrote:
> As I described in the bug, OSX (as documented) does not permit shared
> libraries to refer directly to the environ global variable.

> OK for trunk and 4.9 branch?

For the darwin bits I can approve, Ok.
diff mbox

Patch

--- /dev/null
+++ b/libiberty/environ.h
@@ -0,0 +1,30 @@ 
+/* Declare the environ system variable.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/* On OSX, the environ variable can be used directly in the code of an
+   executable, but cannot be used in the code of a shared library (such as
+   GCC's liblto_plugin, which links in libiberty code).  Instead, the
+   function _NSGetEnviron can be called to get the address of environ.  */
+
+#ifdef __APPLE__
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron ())
+#else
+extern char **environ;
+#endif
--- a/libiberty/pex-unix.c
+++ b/libiberty/pex-unix.c
@@ -23,6 +23,7 @@  Boston, MA 02110-1301, USA.  */
 #include "config.h"
 #include "libiberty.h"
 #include "pex-common.h"
+#include "environ.h"

 #include <stdio.h>
 #include <signal.h>
@@ -389,8 +390,6 @@  pex_child_error (struct pex_obj *obj, const char
*executable,

 /* Execute a child.  */

-extern char **environ;
-
 #if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
 /* Implementation of pex->exec_child using the Cygwin spawn operation.  */

--- a/libiberty/xmalloc.c
+++ b/libiberty/xmalloc.c
@@ -65,6 +65,7 @@  function will be called to print an error message
and terminate execution.
 #endif
 #include "ansidecl.h"
 #include "libiberty.h"
+#include "environ.h"

 #include <stdio.h>