C ++ compiler is missing at startup (SONAME behavior)

I created a program that uses two shared libraries (which I compiled) and is placed as follows:

/home_directory_where_I_compile_and_run_everything -->/lib/libjson_linux-gcc-4.4.6_libmt.so -->/lib/libre2.so.0 

When I compile my program, I pass the relative location of these libraries to the linker, for example:

 g++ ...... stuff ........ my_program.cc lib/libjson_linux-gcc-4.4.6_libmt.so lib/libre2.so.0 

And it compiles fine, however when running the program it does not find libre2.so, and if I check it on ldd, this is what happens:

 .... lib/libjson_linux-gcc-4.4.6_libmt.so (0x00007f62906bc000) libre2.so.0 => not found .... 

Apparently, he admits that the libjson path is relative, but he doesn't do it on libre2.so.0 (he cuts the whole path and just leaves libre2.so.0)

Can someone tell me why this is happening?

Also, is there a way to change this with the g ++ argument?

Best.

* UPDATE * This check! I changed the name libre2.so.0 to stuff.so and then tried to compile essentially the same thing like this:

 g++ ...... stuff ........ my_program.cc lib/libjson_linux-gcc-4.4.6_libmt.so lib/stuff.so 

And it does not work; not only does he fail, he fails because he cannot find "libre2.so.0".

Whyyy?

* UPDATE # 2 *

Output for readelf -d the_program.o

 0x0000000000000001 (NEEDED) Shared library: [lib/libjson_linux-gcc-4.4.6_libmt.so] 0x0000000000000001 (NEEDED) Shared library: [libre2.so.0] 

Now, if I could just do that [libre2.so.0] would be [lib / libre2.so.0], that would be fine.

* UPDATE # 3 *

As @troubadour found out:

When the executable is associated with a shared object that has a DT_SONAME field, then when the executable is launched, the dynamic linker will try to load the shared object specified in the DT_SONAME field, instead of using the file name specified in the linker.

That is why it works with libjson ..... never with libre2.so.0. (libjson ..... therefore has no entry for SONAME).

And I finally found the exact question of what I'm looking for:

Is there a way to tell the gcc linker to ignore the SONAME entries in the shared library file and instead of linking to a specific file path?

+7
source share
4 answers

First, I will answer the second part of your question: why renaming libre2.so.0 did not fulfill what you expected.

The name of the file that you pass to the linker does not matter when you run the executable file (if you do not provide -soname when creating the library - see the second edit below). Dependence is taken from what is called a “sonaim." If you run the readelf command in your library, you can define its name, for example.

 readelf -d libre2.so.0 | grep SONAME 

It doesn't matter if you rename the file. The result of the above command will still give you the same name, so the reason the program still could not find "libre2.so.0".

As for the original part of your question, it all depends on whether the libraries for them are RPATH or RUNPATH and / or the contents of your environment variable LD_LIBRARY_PATH . This is what the runtime linker (ld.so) uses to search for shared libraries. Try

 man ld.so 

for more information.

Since you yourself created the libraries, you will find out if they used the -rpath or -runpath during the final -runpath phase. Alternatively, use readelf again, for example.

 readelf -d libre2.so.0 | grep RPATH readelf -d libre2.so.0 | grep RUNPATH 

I suspect that these two teams will not return anything.

I assume that you have the current directory in LD_LIBRARY_PATH , which will allow the linker to find lib / libjson_linux-gcc-4.4.6_libmt.so at run time, but not libre2.so.0. I notice that you answered my comment on your question to say that your LD_LIBRARY_PATH empty. This is strange.

Did you somehow get the prefix "lib /" in soname for libjson? i.e. readelf command to return soname

 lib/libjson_linux-gcc-4.4.6_libmt.so 

not just

 libjson_linux-gcc-4.4.6_libmt.so 

Also, check what the program requires in terms of soname by running

 readelf -d my_progam | grep NEEDED 

Perhaps the prefix "lib /" is there because you passed it to gcc. If so, then if you use the gcc command given by @enobayram, then it will align the playing field, that is, it will also not be able to find libjson.

The first thing to install is not why it does not find libre2.so.0, but how it can find libjson. If you try to run the executable from another directory, is it still working or is it now not working for libjson? Alternatively, if you copy libre2.so.0 while next to your executable, will this change anything?

Edit

A post on the Fedora forum suggests that the version of ld.so for Fedora has the current directory as its built-in search path. I could not verify this, but that would explain why you are building any libraries at all, given that all other things used by ld.so are missing in your case.

Edit 2

On the ld man page on my system

-soname = name

When creating a shared ELF object, set the internal field DT_SONAME to the specified name. When an executable file is associated with a shared object that has a DT_SONAME field, then when the executable file is executed, the dynamic linker will try to load the shared object specified in the DT_SONAME field, rather than using the file name specified in the linker.

Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009. Free Software Foundation, Inc.

You may copy, distribute, and / or modify this document in accordance with the terms of the GNU Free Documentation License, version 1.3 or any later version published by the Free Software Foundation; without Invariant sections, without front cover textures and without back cover Texts. A copy of the license is included in the "GNU Free Documentation License" section.

So the theory in your comment is correct. If -soname is not explicitly specified when creating the library, then -soname does not exist in the shared object, and the NEEDED field in the executable file simply has the file name provided to the linker, which in your case contains the leading "lib /",.

+11
source

When you link to shared libraries (.so), they must exist in the path of loading your library when the program runs. The place that you provided with the link is not "remembered" in the executable file.

Alternative solutions:

  • put the .so files in the same directory as the executable
  • do LD_LIBRARY_PATH=lib ./program
  • install the .so files to a location in the library path, for example /usr/local/lib , before starting the program.
  • link statically
+3
source

You need to indicate where the shared library is in two situations.

One time binding .
There are several ways:

  • copy the library to some standard directory, for example /usr/local/lib , and install it via ldconfig . Thus, no other option / operation is required.
  • use -L to tell gcc where to find lib

One is in mode .
Also several ways:

  • as the binding time, install it via ldconfig , then no other action is required.
  • using LD_LIBRARY_PATH .

    LD_LIBRARY_PATH = .: $ LD_LIBRARY_PATH. / A.out

  • using rpath to write the search path to the executable

    g ++ main.cpp -lxxx -L / a / b / c -Wl, -rpath, / a / b / c

Just specifying the location of the shared library in the linking phase, for example, through -L , does not mean that when the program starts, the system loader will find the desired library.

+1
source

The correct compiler command line should be:

 g++ ...... stuff ........ my_program.cc -Llib -ljson_linux-gcc-4.4.6_libmt -lre2 

And you must either put the shared objects in the standard directory (for example, / usr / lib) or add your path to LD_LIBRARY_PATH to be able to run the executable.

0
source

All Articles