Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting ABI compatibility issues with GCC

I recently spent a fairly substantial amount of time tracking down a problem that turned out to be caused by compiling a library with -D_GLIBCXX_DEBUG (which tells libstdc++ to use a debug version of the standard library with extra checks) but compiling the client program without. This caused an ABI compatibility problem.

Is there some way I can automatically detect problems like this with GCC? Visual Studio provides the detect_mismatch pragma which I think would have served this purpose, but I'm unaware of any GCC equivalent. GCC does something with embedding a symbol name (e.g. GLIBCXX_3.4.9), and I can imagine schemes that would cause a linking error because of an undefined symbol if a corresponding symbol (e.g. mylib_debug_stl) were not present, but the only ways I can think of to get a use of that symbol are really hacky.

Alternatively, how do other people avoid this issue? Build the checked version of the library to a different name or something like that?

like image 455
EvanED Avatar asked Sep 27 '12 20:09

EvanED


People also ask

Are GCC and Clang ABI compatible?

clang, modulo bugs, is fully C++ ABI compatible with GCC (they both follow the intervendor Itanium ABI) on unix systems. Make sure you use the same standard library for all components because libstdc++ and libc++ are different implementations with completely different object layouts.

What breaks ABI compatibility?

ABI break happens when one binary, e.g. shared object, uses a different ABI when calling functions on another shared object. If both binaries are not ABI compatible, the interpretation of the bytes would be wrong.

What is ABI in GCC?

These details are defined as the compiler Application Binary Interface, or ABI. From GCC version 3 onwards the GNU C++ compiler uses an industry-standard C++ ABI, the Itanium C++ ABI. The GNU C++ compiler, g++, has a compiler command line option to switch between various different C++ ABIs.

What is ABI in C++?

As C++ evolved over the years, the Application Binary Interface (ABI) used by a compiler often needed changes to support new or evolving language features. Consequently, programmers were expected to recompile all their binaries with every new compiler release.


1 Answers

Is there some way I can automatically detect problems like this with GCC?

Only the linker can detect if you link incompatible code, not the compiler.

The alternative linker, gold, can detect some problems with the --detect-odr-violations option.

Alternatively, how do other people avoid this issue? Build the checked version of the library to a different name or something like that?

I just ensure I rebuild everything when I want to use the Debug Mode, I don't think I've ever wanted to keep a library around that was built with Debug Mode. It's meant for debugging, not for normal use.

I rarely use -D_GLIBCXX_DEBUG anyway, I more often do something like:

#if 0
# include <debug/vector>
namespace my_class_stl = __gnu_debug;
#else
#include <vector>
namespace my_class_stl = std;
#endif

struct my_class
{
  typedef my_class_stl::vector<int> container;
  typedef container::iterator iterator;
  // ...
};

Then I change the preprocessor condition when I want to use a Debug Mode vector for that specific class, without affecting every container in the program. Because the change involves writing to the file (and so updating its timestamp) anything that depends on that header will get rebuilt by make, and there are two distinct types, std::vector<int> and __gnu_debug::vector<int>, which have different symbols and can't be confused by the linker.

Just defining _GLIBCXX_DEBUG doesn't cause all dependencies to be rebuilt, and silently alters the definition of std::vector globally, rather than changing specific containers to a different type with a different name, __gnu_debug::vector

like image 69
Jonathan Wakely Avatar answered Oct 05 '22 01:10

Jonathan Wakely