[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Gnulib 64-bit ABI bug with OSX, generic patch proposed
From: |
Jarno Rajahalme |
Subject: |
Gnulib 64-bit ABI bug with OSX, generic patch proposed |
Date: |
Fri, 16 Apr 2010 15:12:20 -0700 |
Sorry for posting this same issue multiple times, but I have a possibly better
proposal for fixing this this time.
I faced the following linking error trying to link octave on OSX with the stock
Apple GCC 4.2 (Xcode 3.2.2) -m64:
dyld: Symbol not found:
__ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE7seekoffElSt12_Ios_SeekdirSt13_Ios_Openmode
Referenced from:
/Users/rajahalm/testing/octave/src/.libs/liboctinterp-3.3.51+.dylib
Expected in: flat namespace
unmangled:
std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char>
>::seekoff(long, std::_Ios_Seekdir, std::_Ios_Openmode)
/usr/lib/libstdc++.6.dylib has an _almost_ matching entry:
__ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE7seekoffExSt12_Ios_SeekdirSt13_Ios_Openmode
unmangled:
std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char>
>::seekoff(long long, std::_Ios_Seekdir, std::_Ios_Openmode)
The difference is that the first parameter to seekoff() should be "long long",
but with gnulib it is "long", as it is of type std::streamoff, which is defined
to be int64_t.
OSX /usr/include/stdint.h typedefs int64_t as "long long". As long as gnulib
stdint.h (re)defines this as "long int" there is going to be this
ABI/mangling/linking problem, even though both definitions result in the same
size of the std::streamoff.
It seems the tests in stdint.in.h are insufficient. Testing for the size of
"long" is not enough, as the name mangling rules are different for "long" and
"long long", even if they are of the same size. stdint.in.h defines int64_t as
"long long int" when @HAVE_LONG_LONG_INT@, provided that "long" is NOT 64 bit.
I propose the following patch (see below) that allows defining int64_t as "long
long int" (same mangling as for "long long"), when defined, even if "long" is
64 bit. With this patch the ABI compatibility is maintained, and linking
succeeds.
However, it is possible that some other platforms need int64_t to be defined as
"long int", when long is 64 bit, causing this change to break the ABI
compatibility on those platforms. So, maybe int64_t should NOT be defined, if
already typedef'ed? But this may be hard to detect with the preprocessor
macros, so maybe a configure time check for int64_t is needed.
Regards,
Jarno
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index a861c07..25719ac 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -135,7 +135,7 @@ typedef unsigned int gl_uint32_t;
/* Do not undefine int64_t if gnulib is not being used with 64-bit
types, since otherwise it breaks platforms like Tandem/NSK. */
-#if LONG_MAX >> 31 >> 31 == 1
+#if LONG_MAX >> 31 >> 31 == 1 && address@hidden@
# undef int64_t
typedef long int gl_int64_t;
# define int64_t gl_int64_t
>> I faced the following linking error trying to compile octave on OSX with GCC
>> 4.3 -m64:
>>
>> dyld: Symbol not found:
>> __ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE7seekoffElSt12_Ios_SeekdirSt13_Ios_Openmode
>> Referenced from:
>> /Users/rajahalm/testing/octave/src/.libs/liboctinterp-3.3.51+.dylib
>> Expected in: flat namespace
>> in /Users/rajahalm/testing/octave/src/.libs/liboctinterp-3.3.51+.dylib
>>
>> unmangled:
>>
>> std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char>
>> >::seekoff(long, std::_Ios_Seekdir, std::_Ios_Openmode)
>>
>> /opt/local/lib/gcc43/libstdc++.6.dylib has an _almost_ matching entry:
>>
>> __ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE7seekoffExSt12_Ios_SeekdirSt13_Ios_Openmode
>>
>> unmangled:
>>
>> std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char>
>> >::seekoff(long long, std::_Ios_Seekdir, std::_Ios_Openmode)
>>
>> The difference is that the first parameter to seekoff() should be "long
>> long", but it is "long", as it is of type std::streamoff, which is defined
>> to be int64_t, if _GLIBCXX_HAVE_INT64_T is defined. This definition is
>> handled differently in GCC 4.4, which does not exhibit this linking problem.
>>
>> GCC 4.0 and 4.2 seem to have the same definition of std::streamoff as GCC
>> 4.3, so this problem exists with those versions as well.
>>
>> OSX /usr/include/stdint.h defines int64_t as "long long". As long as gnulib
>> stdint.h redefines this as "long int" there is going to be this linking
>> problem with GCC 4.3, even though both definitions result in the same size
>> of the std::streamoff :-)
>>
>> I tested this with the following change:
>>
>> *** lib/stdint.in.h~ Fri Apr 2 17:38:10 2010
>> --- lib/stdint.in.h Thu Apr 8 19:29:39 2010
>> ***************
>> *** 135,141 ****
>>
>> /* Do not undefine int64_t if gnulib is not being used with 64-bit
>> types, since otherwise it breaks platforms like Tandem/NSK. */
>> ! #if LONG_MAX >> 31 >> 31 == 1
>> # undef int64_t
>> typedef long int gl_int64_t;
>> # define int64_t gl_int64_t
>> --- 135,141 ----
>>
>> /* Do not undefine int64_t if gnulib is not being used with 64-bit
>> types, since otherwise it breaks platforms like Tandem/NSK. */
>> ! #if LONG_MAX >> 31 >> 31 == 1 && !(defined (__APPLE__) && defined
>> (__MACH__))
>> # undef int64_t
>> typedef long int gl_int64_t;
>> # define int64_t gl_int64_t
>> # define GL_INT64_T
>> #elif defined _MSC_VER
>> # undef int64_t
>> typedef __int64 gl_int64_t;
>> # define int64_t gl_int64_t
>> # define GL_INT64_T
>> #elif @HAVE_LONG_LONG_INT@
>> # undef int64_t
>> typedef long long int gl_int64_t;
>> # define int64_t gl_int64_t
>> # define GL_INT64_T
>> #endif
>>
>> (added lines above for reference)
>>
>> This change causes int64_t to be defined as "long long int", which seems to
>> be equivalent to "long long" for name mangling pusposes.
>>
>> With this change this linking error disappears. However, more fundamentally,
>> it seems that definition of int64_t based on a matching LONG_MAX is not
>> enough in any 64 bit C++ system, due to the name mangling difference between
>> long and long long. The proper thing would be to not redefine int64_t at all
>> if it is already defined as any type that is 64 bits long.
>>
>> Jarno
>>
>>
>>
>>
>>
>
- gnulib stdint.h substitution of int64_t results in a linking error in GCC 4.(3|2|0) on OSX, fix included, Jarno Rajahalme, 2010/04/08
- gnulib stdint.h substitution of int64_t results in a linking error in GCC 4.(3|2|0) on OSX, Jarno Rajahalme, 2010/04/15
- Gnulib 64-bit ABI bug with OSX, generic patch proposed,
Jarno Rajahalme <=
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Jarno Rajahalme, 2010/04/16
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Paolo Bonzini, 2010/04/16
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Jarno Rajahalme, 2010/04/20
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Paul Eggert, 2010/04/23
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Jarno Rajahalme, 2010/04/25
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Jarno Rajahalme, 2010/04/26
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed, Jarno Rajahalme, 2010/04/30