GCC: disguising between GCC versions - gcc

This question was emerged from this question.
The problem is that there is a NVidia driver for Linux, compiled wth GCC 4.5. The kernel is compiled with GCC 4.6. Well, the stuff doesn't work because of the version number difference between GCCs. (the installer says the driver won't work - for details please visit the link above)
Could one disguise a binary compiled with GCC 4.5 to a binary compiled with GCC 4.6? If it is possible, under what circumstances would it work well?

Your problem is called ABI: Application Binary Interface. This is a set of rules (among others) how functions in a piece of code get their arguments (ordering, padding of types on the stack), naming of the function so the linker can resolve symbols and padding/alignment of fields in structures.
GCC tries to keep the ABI stable between compiler versions but that's not always possible.
For example, GCC 4.4 fixed a bug in packed bit-fields which means that old/new code can't read structures using this feature properly anymore. If you would mix versions before and after 4.4, data corruption would occur without any crashes.
There is no indication in the 4.6 release notes that the ABI was changed but that's something which the Linux kernel can't know - it just reads the compiler version used to compile the code and if the first two numbers change, it assumes that running the code isn't safe.
There are two solutions:
You can compile the Nvidia driver with the same compiler as the kernel. This is strongly recommended
You can patch the version string in the binary. This will trick the kernel into loading the module but at the risk of causing data corruption to internal data structures.

Related

Compiler output on different OS Versions

As far as I understand(Correct me if i'm wrong), the output of a compiler depends on the Architecture version used, Compiler, and operating system.
Lets say Im using ubuntu release 16.04 x84-64 and compiling a c file with gcc version 5.4(or any other mix of OS,arch,compiler for the example) .
As I understood it until now, if I were to compile the same c file but with a different ubuntu release, with the same arch and compiler version it should have produced the same assembly code.
After a few tries I have got the impression that this is incorrect, how is this possible?
Does the output of a compiler depend on the release of the specific OS?
One of the examples is compiling https://github.com/tbuktu/libntru on 2 different ubuntu versions and receiving different assembly.
The different OS's may have different versions of the default libraries installed (which get linked into your final application). Thus the end result may be slightly different.
If you are just doing a few ubuntu versions the odds of differences goes down as the overall architecture differences may not be reflected either in your test or may not change on the same os family with the same compiler family for long periods of time. Where you are more likely to see differences in a test like that is as you get older versions of the same distro, newer/newest versions of the compiler are not ported/supported directly as an apt-get. maybe you can get them to work by hand building but gcc in particular is really bad about that their code only builds with relatively recent prior or following versions get too far apart and gcc cant build gcc. What I would first expect to see is strictly due to gcc version differences you start to see differences in the compiler.
A better test is take a simple .c file and build for windows any version (using the same version of gcc built for that system) and ubuntu/linux any version. Should more quickly see differences.
Two different compilers should show differences for reasonably sized projects, or knowledge based targeted small code samples, llvm/clang vs gcc for example. Different versions of the same compiler or compiler family will somewhat by definition show differences over time, does 6.x vs 6.x+1 gcc show differences well yes if you know where to look but often not, but gcc 3.x vs gcc 7.x should and then depending on the test you can narrow in from there.
You have compiler to compiler differences on the same os and system that are expected to show differences.
You have various reasons why system to system differences with the same compiler will show differences.
And then combinations of the above would naturally also show differences.
The bigger question is why do you care, the educational information is that you shouldn't expect the same C source code to build the same way if you change the compiler, compiler settings, or operating system. It can have anywhere from no differences to huge differences based on any of the above. Starting quite simply with optimization and other tuning settings and going from there.

Is it safe to link compiled object files from different GCC versions?

Is it safe to link objects generated from sources compiled with different GCC versions into a shared library?
I assume not, but in case the used GCCs have no difference in regards to code generation and optimization improvement? Is there an information to know which GCC compiler is not backward compatible?
My question is also concerns the binaries, I looked in
https://gcc.gnu.org/onlinedocs/gcc/Compatibility.html
From my understanding, different GCC version would be compatible as long as they Conform to the same ABI
So After doing a research on the web, and reading several GCC release notes, it seems that GCC is backward compatible if there is no ABI change.
In general, this would be stated in the release notes.
I also did some experiment using different GCC compilers and GCC linkers (by different meaning from different versions of GCC) and I got linker errors when it was incompatible (different ABI versions).

Portable method to package C++11 program sources

so, C++11 has been around for a while and, given there already are compilers supporting it on most platforms, it would be nice to use it in some real software -- e.g. one that can be packaged in as-portable-as-possible package, preferably providing ./configure and so.
Because both Clang and GCC currently need -std=c++11 flag to compile c++11 source, and both sometimes require specific flags to work correctly (see for example How to compile C++11 with clang 3.2 on OSX lion? or C++11 Thread not working ), I'm quite afraid that the package won't work on some platforms that already support c++11 because of wrong invocation of compiler.
Q: Is there some standard how to correctly and portably compile c++11? E.g. autotools/autoconf check or some list of compiler/platform directives that describe all possible needed options? Or does the situation come from the fact that c++11 standard implementations are currently marked as "experimental" and the standard will eventually stabilize and become the default choice, not needing any usage of extra compiler flags?
Thanks
-exa
Well, if you`re trying to write portable code, i would recommend using cmake
a very powerful cross-platform, open-source build system.
Using cmake you should be able to identify the compilers available in your current machine and then generate your makefiles using the flags that you want in each case.
I have been using cmake for almost a year by now and it has significantly reduced the time consumed when trying to get a project compiling in different platforms.
I`m using CMake to generate Makefiles of C++11 projects. The only change in CMakeLists.txt I need to do is add the following:
ADD_DEFINITIONS("-std=gnu++11")
ADD_DEFINITIONS("-D_GLIBCXX_USE_C99_STDINT_TR1")
ADD_DEFINITIONS("-D_GLIBCXX_HAS_GTHREADS")
However, as I use Qt, I re-compile QtSDK with a new gcc version 4.8 and get a complete mingw system that use gcc in version 4.8.
Makings these changes, the project compile and run in Windows XP, Windows 7 and linux both 32 and 64 bits. I didn`t test it in OSX yet.

GCC target specificity and binary compatibility

Initial note: The question mentions AIX because it is the initial context but the question really pertains to gcc itself, most probably regardless of the platform.
AIX is supposed to be backwards binary compatible: a C program compiled on AIX 5.1 will run as is on 5.2, 5.3, 6.1 and 7.1.
In my understanding gcc should be built to target a specific system (whether the current one or another one in the case of cross-compiling). So, gcc built on AIX 6.1 targets AIX 6.1, and produces binaries usable on both 6.1 and 7.1 thanks to binary compatibility.
Yet gcc itself built on AIX 6.1 is a 6.1 program, so it should execute on 7.1 as is. Of course if I compile a program with it on 7.1, this program might get linked or use headers specific to 7.1, thus making the resulting binary requiring 7.1. So as far as I understand it, I should be able to run gcc built on AIX 6.1 onto a 7.1 machine, and produce maybe non-optimal yet perfectly valid binaries, although they would require 7.1 as a side effect of linking.
This looks too much like rainbows and unicorns dancing in glittery skies. I smell something fishy but lack any knowledge of gcc innards. Please mighty crowd, enlighten me.
tl;dr: Can gcc built on and targeting a version N of an OS/platform be run and used on version N+1 by virtue of platform binary compatibility to produce binaries running on version N+1? If not, what mechanism would prevent it?
Here's enlightenment: your question is way too general. In order to answer it, someone would have to have knowledge of
the operating systems you care about
the OS versions you care about
the gcc versions you care about
and then research the binary compatibility in this three dimensional matrix.
Mechanisms preventing binary compatibility are too numerous and directly correlate to your OS and compiler vendor's ingenuity at breaking it. One of the more common and documented ways being official deprecation of API calls, removal of compatibility libraries shipped, and bridges being burnt, like going from a.out to ELF.

Can/should libiomp5 and libgomp mix?

We are compiling an application that uses OpenMP. We are using gcc 4.4, with -fopenmp. The app also uses IPP, which includes its own version of OpenMP (libiomp5). (Note: we are disabling IPP's internal threading by calling ippSetNumThread(1). According to Intel's documentation, this should avoid conflicts with other threading libraries. However, linking with IPP still links in libiomp5.so.)
Since libiomp5.so is already linked in, we have not been linking with libgomp.so (gcc's version of OpenMP). For a long time this has worked, but after a seemingly inconsequential change we started seeing very odd OpenMP-related crashes on one of four platforms we support (the other three platforms still work fine).
I can make the crashes go away if I link in libgomp.so as well as libiomp5.so.
I have a couple questions about this:
Is linking with both these libraries safe? It seems like they would both define the same symbols.
Is there a way to tell what version of OpenMP libiomp5.so supports? With gcc 4.4, libgomp.so should be at OpenMP v3.0. I can't find any information in Intel's documentation about the OpenMP version of libiomp5.so.
Since no one has answered for a few days, I'll just report what I've found out independently:
Is linking with both these libraries safe?
No. Here's the most useful page I found on this topic:
http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/optaps/common/optaps_par_openmp_multiple_compilers.htm
Intel recommends that if you are going to be mixing IPP's internal OpenMP threading with your own OpenMP threading, you link to libiomp5 instead of your compiler's OpenMP library. The current version of libiomp5 provides "source compatibility and object-level interoperability" with gcc's OpenMP, but only if you are using gcc "4.42" (sic; I assume they mean 4.4.2) or later.
Is there a way to tell what version of OpenMP libiomp5.so supports?
Yes. Set the environment variable KMP_VERSION=1, then run your application. You'll get some debugging output printed by libiomp5 to your console. If you are using IPP v7 or later, one line will be something like
Intel(R) OMP API version: 3.0 (200805)
If you are using IPP 6, it won't tell you the API version, but it will tell you when it was built and with which version of the Intel compiler. Then you can check and see what version of OpenMP that compiler supported. (11.0 was the first version of the Intel compiler to support OpenMP v3.0.)

Resources