Why the linker insists to find the shared libraries at link time? - linker

I don't understand why linker fails if he does not find one of the shared libraries I pass to it using -l flag.
They are shared, so their code is not copied into the binary, so in any case when process will start it will need to look for those libraries again in order to use their code.
So what is the purpose of verifying it in link stage, isnt it obsolete? lets say he found them, does it guarantees that they will also exist when the process is executed? obviously no.. Same goes in the opposite direction, so I don't see any logic in verifying it in link time, but since I know that the people that wrote GCC are obviously very smart, I wonder what do I miss..

Related

What can interfere with library load path

I have a C program (IDS vortex) which uses a library libbsf. I have several more or less identical ubuntu machines and vortex works fine on all bar one of them.
On that one it fails to find the library. Explicitly setting LD_LIBRARY_PATH=/usr/local/lib works.
/usr/local/lib is in /etc/ld.so.conf as well as /etc/ld.so.conf/libc.conf.
Running ld.config -v finds the library.
I am baffled as to what can be interfering and stopping this executable finding the library at run time.
I have copied the executable to one of the other machines where it finds the library.
Originally I distributed both the executable and library to all machines using puppet and when it failed on one I ended up compiling all the bits on the actual machine before deciding that it really was an issue with the library path. Setting LD_LIBRARY_PATH verified that.
Suggestions solicited!!
changing anything in /etc/ld.so.conf without running ldconfig will cause problems. In this case I don't know how things got out of sync but you can not assume that the current state of ld.so.conf reflects what is happening at run time.
Pointing me at strace was useful (thanks!) I started hacking ld.conf and nothing I did made any difference. Then a colleague pointed me to ldconfig.

Update shared libraries without restarting processes

If my process is loading a .so library and if a new version of the library is available is it possible to switch to the new library without doing a process restart ? Or the answer depends on things like whether there is a parameter change to one of the existing functions in the library ?
I am working in a pretty big system which runs 100s of processes and each loading 10s of libraries. The libraries provide specific functionality and are provided by separate teams. So when one of the library changes (for a bug fix lets say) ideal thing would be to publish it under-the-hood without impacting the running process. Is it possible ?
EDIT Thanks! In my case when a new library is available all the running processes have to start using it. Its not option to let them run with the old version and pick-up the new one later. So it looks like the safer option is to just reload the processes.
You cannot upgrade a linked library on the fly with a process running.
You could even try to, but if you succed (and you'll not fail with a "text file is in use" error message), you'll have to restart the process to make it mapping the new library into memory.
You can use lsof command to check which libraries are linked in (runtime or linktime):
lsof -p <process_pid> | grep ' mem '
One interesting technique, although it is somewhat prone to failure in the checkpoint restore step, is to do an invisible restart.
Your server process or whatever it is, saves all its necessary information into disk files. Including the file descriptor numbers and current states. Then, the server process does an exec system call to execute itself, replacing the current version of itself. Then it reads its state from the disk files and resumes serving its file descriptors as if nothing happened.
If all goes well, the restart is invisible and the new process is using all of the updated libraries.
At the very least, you have to make sure that the interface of the library does not change between versions. If that is assured, then I would try looking into dynamically loading the libraries with dlopen/dlsym and see if dlclose allows you to re-load.
I've never done any of this myself, but that's the path I'd pursue first. If you go this way, could you publish the results?
Linux provides several dynamic loader interfaces, and process can load dynamic librarys when running. dlopen and dlsysm provided by linux may solve your problem.
If you expect libaries to change on a fairly regular basis, and
you expect to maintain up-time, I think that your system
should be re-engineered so that such libraries actually become
loosely coupled components (e.g. services).
Having said that, my answer to the question is yes: under certain
circumstances, it possible to update shared libraries without
restarting processes. In most cases I expect it is not possible,
for instance when the API of your library changes, when the
arrangement of your data segment changes, when the library
maintains internal threads. The list is quite long.
For very small bug fixes to the code, you can still make use
of ptrace to write to the process memory space, and from
there redo what /lib/ld-linux.so does in terms of dynamic
linking. Honestly, it is an extremely complex activity.
ldd the binary of your process is one way to find out. although it is theoretically possible, it is not advisable to tinker with the running process, although i am sure utilities exist such as ksplice that tinker with the running linux kernels.
you can simply upgrade and the running process will continue with the old version, and pick up the new version when it restarts, assuming that your package management system is good and knows what is comptible to install.
You might want to learn about shared library versioning and the ld -h option.
One way to use it is as follows:
You maintain a version counter in your build system. You build the shared library with:
ld ..... -h mylibrary.so.$VERSION
however, you put it in your dev tree's lib as just plain mylibrary.so. (There's also a hack involving putting the entire .so into a .a file).
Now, at runtime, processes using the library look for the fully-versioned name. To roll out a new version, you just add the new version to the picture. Running programs linked against the old version continue to use it. As programs are relinked and tested against the new one, you roll out new executables.
Sometimes you can upgrade an in-use .so, and sometimes you cannot. This depends mostly on how you try to do it, but also on the safety guarantees of the kernel you're running on.
Don't do this:
cat new.so > old.so
...because eventually, your process may try to demand page something, and find that it's not in the correct spot anymore. It's a problem because the addresses of things may change, and it's still the same inode; you're just overwriting the bytes in the file.
However, if you:
mv new.so old.so
You'll be OK on most systems, because your running processes can hold onto a now-unnamed inode for the old library, while new invocations of your processes get the new file.
BUT, some kernels don't like to let you mv an in-use .so, perhaps out of caution, perhaps for their own simplicity.

Supplying different library/function at link time

If I want to clone a library and change just one function, say memcpy or memmove, and have an already built executable link to it for debugging/exploration purposes, what is the proper way to do this?
I am guessing I need to recompile the entire library with my modifications, but is there another way to do this?
I understand that there are things like malloc hooks but this seems to be a special case for malloc.
I am curious about the specifics for how valgrind and gdb do this from within another program, if someone has a resource on that.
I am interested in mac and linux solutions. On linux I've used LD_LIBRARY_PATH before - is this all that I need to do besides have the library names the same? How would I do this on mac?
For those curious as to why I want to do this, the purpose is for experimental music. I am doing this to sonify memory operations, so memcpy/memmove will work as normal but the data accessed will also be sent to the sound card. I know there are other ways of doing this (I have done a few other methods already,) but currently I am interested in focusing on memcpy/memmove, so I will appreciate it if you can restrict your answers to this focus.
You can use LD_LIBRARY_PATH to cause a program to load a shared object library different from the usual one. But if you want to replace just one function (or a few) rather than a whole library, you can use LD_PRELOAD to cause the linker (ld.so) to load a particular shared object early on, and your program will use the symbols (functions) in there rather than looking for them in the usual places.

Trace all calls from a program?

A program is installed on 2 computers. A certain library is working correctly in one computer but not working at all in the other. I wonder if a library is missing.
I'm using strace so I can see which libraries are being called by the program at runtime. All libraries mentioned by strace are correct but does strace also detect if one library calls another library or file ? Any way to detect this scenario ?
Yes strace will detect calls from loaded libraries.
If you want to trace library calls (not system ones), use ltrace
It sounds like you want to view your app's function call graph, i.e. which functions call one another, which library they live in, etc. If so, you may want to check out the callgrind tool (which is part of valgrind).
Here is an example that uses callgrind to profile some code.
Once you've used callgrind to generate profile data for your app, load it into Kcachegrind to visualize it. It's simple point-and-click: highlight function, see callers/callees, view the call graph, and so on. I've found it quite useful in similar circumstances.
To check for libraries missing, run ldd /full/path/to/program
For programs using Clang to compile, try get call trace of the programs with Xray. It heuristically instruments part of a program and has very low runtime overhead.

CMake: how to produce binaries "as static as possible"

I would like to have control over the type of the libraries that get found/linked with my binaries in CMake. The final goal is, to generate binaries "as static as possible" that is to link statically against every library that does have a static version available. This is important as would enable portability of binaries across different systems during testing.
ATM this seems to be quite difficult to achieve as the FindXXX.cmake packages, or more precisely the find_library command always picks up the dynamic libraries whenever both static and dynamic are available.
Tips on how to implement this functionality - preferably in an elegant way - would be very welcome!
I did some investigation and although I could not find a satisfying solution to the problem, I did find a half-solution.
The problem of static builds boils down to 3 things:
Building and linking the project's internal libraries.
Pretty simple, one just has to flip the BUILD_SHARED_LIBS switch OFF.
Finding static versions of external libraries.
The only way seems to be setting CMAKE_FIND_LIBRARY_SUFFIXES to contain the desired file suffix(es) (it's a priority list).
This solution is quite a "dirty" one and very much against CMake's cross-platform aspirations. IMHO this should be handled behind the scenes by CMake, but as far as I understood, because of the ".lib" confusion on Windows, it seems that the CMake developers prefer the current implementation.
Linking statically against system libraries.
CMake provides an option LINK_SEARCH_END_STATIC which based on the documentation: "End a link line such that static system libraries are used."
One would think, this is it, the problem is solved. However, it seems that the current implementation is not up to the task. If the option is turned on, CMake generates a implicit linker call with an argument list that ends with the options passed to the linker, including -Wl,-Bstatic. However, this is not enough. Only instructing the linker to link statically results in an error, in my case: /usr/bin/ld: cannot find -lgcc_s. What is missing is telling gcc as well that we need static linking through the -static argument which is not generated to the linker call by CMake. I think this is a bug, but I haven't managed to get a confirmation from the developers yet.
Finally, I think all this could and should be done by CMake behind the scenes, after all it's not so complicated, except that it's impossible on Windows - if that count as complicated...
A well made FindXXX.cmake file will include something for this. If you look in FindBoost.cmake, you can set the Boost_USE_STATIC_LIBS variable to control whether or not it finds static or shared libraries. Unfortunately, a majority of packages do not implement this.
If a module uses the find_library command (most do), then you can change CMake's behavior through CMAKE_FIND_LIBRARY_SUFFIXES variable. Here's the relevant CMake code from FindBoost.cmake to use this:
IF(WIN32)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ELSE(WIN32)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ENDIF(WIN32)
You can either put this before calling find_package, or, better, you can modify the .cmake files themselves and contribute back to the community.
For the .cmake files I use in my project, I keep all of them in their own folder within source control. I did this because I found that having the correct .cmake file for some libraries was inconsistent and keeping my own copy allowed me to make modifications and ensure that everyone who checked out the code would have the same build system files.

Resources