bitwiseworks / gcc-os2

Port of GCC compiler to OS/2
GNU General Public License v2.0
16 stars 2 forks source link

libstdc++ DLL binary incompatibility #7

Closed dmik closed 4 years ago

dmik commented 4 years ago

While working on #6, I discovered the following. Given that we use our standard toolchain for our GCC 9.x build, the C++ DLL is now called stdc++6.dll — just like on all other platforms. However, we provide it as stdcpp6.dll in the current set of 4.x RPMs (it was @ydario's decision — perhaps because + chars are something special that sometimes needs to be quoted). And this DLL is used by all C++ apps recently built using our RPM tool chain. So we need a forwarder for it.

Creating forwarders is easy per se but we've got a problem with missing symbols. The following ones from stdcpp6.dll (which is GCC 4.9.2) are missing from the new GCC 9.x DLL:

__ZN11__gnu_debug17_S_debug_messagesE
__ZNKSt11__use_cacheISt18__moneypunct_cacheIcLb0EEEclERKSt6locale
__ZNKSt11__use_cacheISt18__moneypunct_cacheIcLb1EEEclERKSt6locale
__ZNKSt19istreambuf_iteratorIcSt11char_traitsIcEE6_M_getEv
__ZNKSt5ctypeIcE2isEjc
__ZNSt12__basic_fileIcEC1EP7_fmutex
__ZNSt12__basic_fileIcEC2EP7_fmutex

Feeding it to c++filt gives this:

__gnu_debug::_S_debug_messages
std::__use_cache<std::__moneypunct_cache<char, false> >::operator()(std::locale const&) const
std::__use_cache<std::__moneypunct_cache<char, true> >::operator()(std::locale const&) const
std::istreambuf_iterator<char, std::char_traits<char> >::_M_get() const
std::ctype<char>::is(unsigned int, char) const
std::__basic_file<char>::__basic_file(_fmutex*)
std::__basic_file<char>::__basic_file(_fmutex*)

Re __gnu_debug::_S_debug_messages, I have to figure that out. The rest looks related to these changes by @komh: 203e99b9081c6951f5ac88bb6b950ac9ec779e21 (native C++11 thread support) and 2eafb765c8c7e63f7d481b2ac32fa51f34085899 (native C++ locale support). I will try to look on how we can still provide these symbols in the forwarder but that will definitely take some time. If we fail to do so, we will have to use our legacy RPM machinery and provide a binary build of stdcpp6.dll from 4.9.2 RPMs instead of a forwarder. I don't like this solution very much because it will double memory usage occupied by C++ classes when two apps using different DLLs are up and running.

More over, there is another problem. Even before stdcpp6.dll it was named just stdcpp.dll. This was for GCC RPMs for version 4.4.6. And there are still some apps built with GCC 4.4.6 and therefore using this DLL. Creating a forwarder for it is even harder as there are much more missing symbols. Currently, I don't know why as ABI should still be the same (see here) — perhaps the reason is that Yuri built these DLLs manually instead of letting the GCC makefie system do it. And that's not the only problem. The other one is that the package providing it is named libstdc++ (as opposed to libstdc++6 which provides stdcpp6.dll in 4.9.2 RPMs). And libstdc++ is the canonical name of the package. Our new 9.x RPMs (as well as all other platforms) have it like that. This means that it won't be possible to have both libstdc++ packages (4.4.2 one and 9.x one) to be installed at the same time. I will also try to create a forwarder (which means resolve all missing symbols) and then decide. If I fail, we will use the legacy RPM machinery as well here.

Anyway, it will take a few days to sort that out.

dmik commented 4 years ago

Re __gnu_debug::_S_debug_messages, it's quite interesting. In earlier GCC it was const char* _S_debug_messages[]. Later they added one more const so it became const char* const _S_debug_messages[]. First, it changed the mangled symbol name from __ZN11__gnu_debug17_S_debug_messagesE to __ZN11__gnu_debugL17_S_debug_messagesE. Second, it made this symbol have internal linkage (as per C++ standard, this is the default behavior for all const declarations, see e.g. (https://stackoverflow.com/questions/998425/why-does-const-imply-internal-linkage-in-c-when-it-doesnt-in-c)[here]). So it has a different name now and doesn't even get exported from the DLL any more. I think it's not really needed outside as not even declared in any header. I will simply comment it out.

dmik commented 4 years ago

Regarding std::__basic_file<char>::__basic_file(_fmutex*), It should be __gthread_mutex_t instead of _fmutex but in the Knut's version it is a typedef (hence the original type is picked up). @komh declared it as a structure, so it becomes the right one. Given that this is an internal class (declared in an internal header), it should be safe to just remove it as well.

dmik commented 4 years ago

The other functions seem to have been removed from exports because they are very simple inlines and the new GCC sees no need to provide their precompiled bodies. So should be commented out too. Ok, I will try that.

dmik commented 4 years ago

Regarding the 4.4.6 stdcpp.dll, it misses more: like ___new_handler and a bunch of defines from the __gnu_cxx namespace. The first one got internal linkage in 2013 and therefore is not exported any more (and for those that need it, it will be taken from our libc066.dll wrapper which takes it from the static C++ library for GCC 3.x). The rest seems to be internal private stuff which was not intended to be ever exported. I guess it can also be safely removed.

So it seems that we are able to provide wrappers rather than legacy RPMs — which is better. I will try that all out.

dmik commented 4 years ago

There seems to be no compatibility problems with the new forwarders released in RPMs from #6. Closing this.