[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed
From: |
Jarno Rajahalme |
Subject: |
Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed |
Date: |
Fri, 16 Apr 2010 15:20:03 -0700 |
P.S.: Unfortunately my lack of C++ skill do not allow me to produce a simple
test case that would reproduce this error. The symbol has too many levels of
templates for me.
Jarno
On Apr 16, 2010, at 3:12 PM, ext Jarno Rajahalme wrote:
> 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, 2010/04/16
- Re: Gnulib 64-bit ABI bug with OSX, generic patch proposed,
Jarno Rajahalme <=
- 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