bug-gnulib
[Top][All Lists]
Advanced

[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
>>> 
>>> 
>>> 
>>> 
>>> 
>> 
> 
> 
> 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]