This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Darwin assert.h / shared libgcc mess
- From: Zack Weinberg <zack at codesourcery dot com>
- To: gcc at gcc dot gnu dot org, Stan Shebs <shebs at apple dot com>, Andrew Pinski <apinski at apple dot com>, Richard Henderson <rth at redhat dot com>
- Date: Mon, 15 Nov 2004 12:50:17 -0800
- Subject: Darwin assert.h / shared libgcc mess
I sat down to look into the problems with <assert.h> on Darwin, which
were exposed by Andrew Pinski's patch on Nov 3
* config/darwin.h (REAL_LIBGCC_SPEC): Define to use shared
libgcc for shared libraries.
As I suspected, the apparent problem is just the tip of a very large
iceberg. I have traced it pretty far back, and would now like to
discuss a solution, before I go off and implement it.
1) /usr/include/assert.h on Darwin depends on __eprintf being provided
by libgcc. This is not terribly surprising, considering that GCC
has been the system compiler for Darwin since NeXT days.
i) It is also seriously non-ISO-C compliant. This is because someone
blindly copied the results of a buggy fixincludes edit into
Darwin's CVS tree. [The fixincludes edits broken_assert_stdio and
broken_assert_stdlib both produce an <assert.h> which is
idempotent. This is wrong.]
Given (1), IMO the correct thing to do is put __eprintf into
libgcc.dylib on Darwin; Andrew's proposed fix isn't ISO compliant
either (assert() is required to write to stderr, but <assert.h> is
required not to declare "stderr", or "fprintf" or "abort" for that
matter). However, when one attempts to fix that, one encounters
another set of problems:
2) There is no way to tell mklibgcc.in to add something from libgcc2.c
to both libgcc.a and libgcc.so. Even if there were, by itself that
wouldn't work, because
3) ... the version script would knock it out again. However, there
*is* a facility for adding target-specific version map entries.
2i) ... but this doesn't matter, because as far as I can tell
t-slibgcc-darwin is not actually *using* the generated version map
3i) ... and that is fortunate, because (a) as far as I can tell,
Darwin ld does not support full-fledged symbol versioning (it does
support flat export lists), and (b) libgcc-darwin.ver is out of
sync with libgcc-std.ver. [And the same is true for
config/sh/libgcc-std.ver, incidentally.]
---
My proposed fix for all this is as follows.
1) Ship a *correct* assert.h, as a replace-entire-file fixincludes
edit, which recognizes the broken Darwin /usr/include/assert.h. If
I can swing it, it will also subsume the buggy
broken_assert_{stdio,stdlib} fixes. This corrected assert.h will
continue to use __eprintf. Alternatively, if people prefer, it
could use the more recent convention of __assert, per, eg. FreeBSD
/usr/include/assert.h. (The advantage of this is there aren't
copies of the "%s:%d:%s: assertion failed: %s" string constant
everywhere that uses assert.)
2) Put __eprintf back into the shared libgcc, as an exported symbol,
for all !inhibit_libc targets, so that fixincludes can rely on its
being there. (If we instead use __assert, then __eprintf will
remain a static-library-only backward compatibility symbol.)
3) For the sake of future flexibility, move the hardwired list of
static-and-shared functions from mklibgcc.in to the Makefile so
that it can be adjusted in t-fragments.
4) Add the ability to add a leading underscore to all symbol names to
mkmap-flat.awk and mkmap-symver.awk. Also add the ability to
delete symbols from the list, in a target-specific .ver file.
Update Darwin and SH target configuration to match, and delete the
out-of-sync libgcc-darwin.ver and config/sh/libgcc-std.ver.
5) Determine for certain whether or not Darwin ld supports symbol
versioning. Correct t-slibgcc-darwin to use the appropriate mkmap
file and to actually apply the map to the generated libgcc.dylib.
i) Nudzh the Darwin developers to put __assert in libSystem and
provide a correct /usr/include/assert.h (y'all can just copy it
from FreeBSD! Only with attribute noreturn, please).
Thoughts?
zw