Is there a way to set the NEEFED field for an elf during a connection?

Given that the executable is like this:

>objdump -x someprog | grep c++ NEEDED libstdc++.so.6 

I want to change the requirement for the full version (including the minor version and the fix level):

 >objdump -x someprog | grep c++ NEEDED libstdc++.so.6.0.22 

I know two ways to do this:

  1. create a dummy library on this subject ( forcing or preventing the use of a specific minor version of libstdc ++ )
  2. use patchelf
  > patchelf --add-needed libstdc ++. so.6.0.22 someprog
     > objdump -x someprog |  grep c ++
     NEEDED libstdc ++. So.6
     NEEDED libstdc ++. So.6.0.22

(I did not calculate the working command line for -replace-needed)

Both of them feel like hacks to me. Is there a way to achieve this at compile time or link time using the appropriate -Wl flags for gcc?

Ideally, I want to avoid using -nostdlib since I need not only libstd ++, but libc and everything else that I need standard versions for.

For a regular library, just linking the specific version for libstdc ++ is enough, itโ€™s not (or rather, I suspect that -stdlib will override the subsequent full names that I provide).

Prerequisites: I have executables that require a later version of libstdc++ than is installed on the system. Unfortunately, the installed version may be the same major version, and if so ld would be happy to use the system version, since it corresponds to the libstdc++.so.6

I prefer not to statically link, as I actually want to install many small programs that share the same C ++ runtime, and this will greatly inflate the installation.


Some information about my library search path is available here:

ld --verbose | grep SEARCH_DIR SEARCH_DIR ("/ usr / x86_64-redhat-linux / lib64"); SEARCH_DIR ("/ USR / lib64"); SEARCH_DIR ("/ USR / local / lib64"); SEARCH_DIR ("/ lib64"); SEARCH_DIR ("/ USR / x86_64-RedHat-Linux / Library"); SEARCH_DIR ("/ USR / local / library"); SEARCH_DIR ("/ Lib"); SEARCH_DIR ("/ USR / Lib");

In my case, it is clear that / usr / lib64 searches before the RPATH executable, which:

 >objdump -x /opt/foo/bin/bar | grep PATH RPATH $ORIGIN/../lib64/private:$ORIGIN/../lib64:$ORIGIN/ 

man ld.so suggests a search order:

If the library dependency does not contain a slash, it is executed in the following order:

  o (ELF only) Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated. o Using the environment variable LD_LIBRARY_PATH. Except if the executable is a set-user-ID/set-group-ID binary, in which case it is ignored. o (ELF only) Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if present. o From the cache file /etc/ld.so.cache, which contains a compiled list of candidate libraries previously found in the augmented library path. If, however, the binary was linked with the -z nodeโ€ flib linker option, libraries in the default library paths are skipped. Libraries installed in hardware capability directories (see below) are preferred to other libraries. o In the default path /lib, and then /usr/lib. If the binary was linked with the -z nodeflib linker option, this step is skipped. 

Similar to https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf

Both seem to be surpassed by actual use, but in reality it is not. look for symbolic links:

 >LD_LIBRARY_PATH= LD_DEBUG=libs ldd /opt/foo/bin/bar 21720: find library=libstdc++.so.6 [0]; searching 21720: search path=/opt/foo/bin/../lib64/private:/opt/foo/bin/../lib64:/opt/foo/bin (RPATH from file /opt/foo/bin/bar) 21720: trying file=/opt/foo/bin/../lib64/private/libstdc++.so.6 

This is an interaction with another question that I installed a shared imported library with the necessary links, where it was stated that the links are not required. They are clearly necessary if you did not specify the full semantic version.

0
source share
2 answers

I think I answered my problem, although not the question I really asked.

RPATH searches up to LD_LIBRARY_PATH . The reason /usr/lib64/libstdc++.so.6 selected, not libstdc++.so.6.0.22 is the lack of a symbolic link from /where/i/installed/libstdc++.so.6 to /where/i/installed/libstdc++.so.6.0.22

Thus, the rule complies with the standards of your platform (where they are reasonable). In this case: Whenever you install a shared library, also set the expected links.

I think that the actual question I asked is still technically interesting, so I will still accept the best answer to this question if anyone has (even years later).

+1
source

This will not work, because libstdc++.so.6.0.22 will export the same characters as the libstdC ++ system, and you will get a wild mix between the two libraries (provided that you really changed the name of the new version of libstdC ++).

You must either link the entire libstdC ++ statically (this may require a static version of the PIC library), and not export any characters (possibly with the script linker version) or statically link only new characters.

The second approach is currently the best option: it allows you to use most of the new language features, but you still have a lot of compatibility with the rest of the system (especially if you configured GCC with --with-default-libstdcxx-abi=gcc4-compatible ), and you do not need to install any additional shared objects for deployment. This is how the Toolset developer toolkit provides newer versions of GCC (and I believe the SUSE Linux Toolchain Module ). Full static binding causes problems if C ++ objects are passed across the boundaries of shared objects (including exception handling), and this kind of selective static communication avoids many of these problems.

+1
source

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


All Articles