Forcing or preventing the use of a particular minor version of libstdc ++

To take advantage of C ++ 11 and C ++ 14, I have an application compiled using a newer version of gcc (4.9.1) and therefore a newer version of libstdC ++. The application consists of many small programs, so I link to libstdC ++ as a shared library, and not to a static one (i.e. I don't want to use -static-libstdC ++)

I want to send a new version of libstdC ++ using an application in / opt // lib 64 (note that this is specifically allowed for exclusion from the GPL)

The new version of libstdC ++, therefore, differs from the version on the target platform only in a minor version. libstdC ++ is intended for forwarding so that existing programs can use the new version of the library. However, I observed subtle differences in behavior (i.e., Errors) when some programs use the new version rather than the older one. I want to prevent this.

I also found that ld will try to link my application with the system version of libstdC ++, if only I put / opt // lib 64 earlier on LD_LIBRARY_PATH. Presumably, you can force the specific version to be bound with -l:<library>.<version> , however this does not work. I suspect this will be for a user-created library, but not for a language runtime such as libstd ++, because gcc itself creates a script linker. Also on one of my target platforms (RHEL5) this is not even clear to gcc / ld. I assume this is possible with -nostdlib and binding in everything that is required (e.g. -lgcc) in my build system and not leave it on gcc, which I would prefer. I have not tried this yet.

A simple way to work around the solution is to have LD_LIBRARY_PATH contain / opt // lib 64 when the application starts, and not otherwise or equally, I could use LD_PRELOAD with the correct version of the library. The problem with this is if someone decides to ignore my advice and runs

 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/<vendor>/lib64 

this can lead to subtle and difficult to diagnose problems. So I was looking for a better way.

I wondered if I could somehow rename libstdC ++ as lib_stdC ++ and associate it with this sonata. Renaming libstdc ++ is not enough, since you need to change the username in the file as indicated by readelf. i.e

 0x000000000000000e (SONAME) Library soname: [libstdc++.so.6] 

If you do this with a regular gcc related program, even using -l:stdc++.so.6.0.20 , say that you notice this gives the main version, not the specific minor version. i.e.

 readelf -d <myapp> 0x0000000e (SONAME) Library soname: [libstdc++.so.6] 

but not:

 0x0000000e (SONAME) Library soname: [libstdc++.so.6.0.20] 

So, instead, I created a dummy shared library with the sound I want to depend on in order to add the dependency as follows:

 gcc dummy.o -Wl,-soname,lib<vendor>_stdc++.so.6.0.20 -nostdlib -shared -o lib<vender>_dummycpp.so 

(where dummy.o is an empty object file made from an empty source file to stop -nostdlib leading to complaints)

then

 gcc <myapp> -l<vendor>_dummycpp 

optionally I now get:

 readelf -d <myapp> 0x0000000000000001 (NEEDED) Shared library: [lib<vendor>_stdc++.so.6.0.20] 

instead

 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6] 

The dummycpp library contains all the characters in libstdc ++ because it is libstd ++, so gcc does not need to bind to soname libstdc ++ at all. I seem to have completely solved the problem.

This strikes me as a slightly hacky solution, so the questions I want to ask here are as follows:

  • Is that a good idea?

  • If not, why?

  • Is there a better / more correct way?

Note: if you pack libstd ++ with a different name (for example, lib_std ++. So.6.0.20) in RPM, you will get the missing dependency on it and must be installed using --nodeps. This is because RPM scans connection time dependencies. A workaround for this is also to install a dummy library. The RPM then picks up the sonamer from the dummy library and does not claim to be missing.

+6
source share
1 answer

Introduction to the libstdC ++ FAQ How can I guarantee that a dynamically linked library will find links to a section of the Search for Dynamic or Shared Libraries manual that explains how to use RPATH instead.

My preferred method is to use RPATH $ORIGIN , which means that the dynamic library dependency lookup starts in the same directory as the binary (see ld.so (8) ). Therefore, if you link to '-Wl,-rpath,$ORIGIN' (note the quotes to prevent the shell from spreading $ ORIGIN), you can install the shared libraries in the same directory as your installed binary, and they will found when your binary is launched. Or use '-Wl,-rpath,$ORIGIN/../lib' if you prefer separate bin and lib directories under some installation prefix.

When the library is installed next to the binary in some custom path that ldconfig does not scan, and no LD_LIBRARY_PATH ruins the environment, the new libstdC ++ will never be found by applications that should not use this version.

Make sure you also set the libstdc++.so.6 symbolic link pointing to the libstdc++.so.6.0.20 file so that DT_NEEDED for libstdc++.so.6 can find the file.

+2
source

Source: https://habr.com/ru/post/975668/


All Articles