difference between .so.0 and .so.0.0.0 files - linux

Im using a market data source implementation that contains .so.0 files. However these are 'soft links' to actual .so.0.0.0 files. Why is this done?
When I try to copy these .so.0 links, it ends up copying an exact replica of the .so.0.0.0 file but with a .so.0 prefix.
Added comment:
so I have a libfoo.so file, and it is being accessed by java through jni. This libfoo.so file is actually a soft link that points to libfoo.so.0.0.0 What happens if I don't have libfoo.so. How does java/or any other compiled code, figure out that libfoo.so.0.0.0 if the shared object to use?

This is so programs can bind to either any version of libfoo that has the same interface (I want the latest updates to libfoo), or bind to a specific version (I want stability and only the exact version I tested against).

The .0 and .0.0.0 files exist so that versioning can happen:
foo.0 represents the .0 version of a library. All .0 versions of the library will use the same interface, but there may be different implementations. (Hopefully, the later implementations will have fewer bugs than the earlier ones.)
foo.0.0.0 represents a specific implementation of the .0 version.
It's not useful, now, to have the soft-link. But here's what could happen:
The programmer of foo finds a bug in his library. He releases foo.0.0.1. And foo.0 now links to foo.0.0.1. Then two things happen:
All files that link to foo.0 will automatically update to foo.0.0.1.
All files that link to foo.0.0.0 will continue to use the old foo.0.0.0

Related

How to replace a native dynamic library file permanently and appropriately

I try to develop a thirdparty unixODBC driver, it is a secondary development based on the original file libodbc.so.2.0.0.
so I want to rename 'libodbc.so.2.0.0' to 'libodbc.so.2.0.0_renamed'. And soft link my dynamic library file to libodbc.so.2.0.0.
But I found an issue bothering me, when I rename native file and run 'sudo ldconfig', the file named 'libodbc.so.2' automatically linked to the renamed file 'libodbc.so.2.0.0_renamed', as below:
I could not understand that:
why it occurs;
how to appropriately replace the library.
I don't have enough ackownledge about linux, so that I failed to get any keyword to search and deal with it.
Could you help me, thank you very much!
Shared objects under GNU/Linux follow a specific version naming scheme, which is known by the loader (and OS component, actually part of libc framework) to determine if a newer library is retro-compatible with some older version to which a binary was originally linked against. By adding the renamed suffix, you are violating the convention and the dynamic linking system is getting confused. You should renamed as suggested by #Bodo above.
In addition, perhaps rather than using rename, you might consider using the very versioning scheme. From GNU Build System (aka Autotools) manual, the version cheme is like it follows:
Versioning: CURRENT:REVISION:AGE
CURRENT The latest interface implemented.
REVISION The implementation number of CURRENT (read: number of bugs fixed...)
AGE The number of interfaces implemented, minus one.
The library supports all interfaces between CURRENT − AGE and CURRENT.
If you have
not changed the interface (bug fixes) CURRENT : REVISION+1 : AGE
augmented the interface (new functions) CURRENT+1 : 0 : AGE+1
broken old interface (e.g. removed functions) CURRENT+1 : 0 : 0
Therefore a possible history of your lib might be:
1:0:0 start
1:1:0 bug fix
1:2:0 bug fix
2:0:1 new function
2:1:1 bug fix
2:2:1 bug fix
3:0:0 broke api
3:1:0 bug fix
4:1:1 bug fix
5:0:0 broke api
You might, for instance, call the older and newer versions of libodbc.so.x.y.z, according to your needs. Just an idea.

Binary linked against different shared libraries of the same package

I have 2 shared libraries conflicting with each other, and other binaries linked against them. To be more detailed, I have something like this:
top-lib1.so linked with libprotobuf.so;
top-lib2.so linked with libprotobuf-lite.so;
binary linked with top-lib1.so and top-lib2.so.
The problem is that when I launch my binary, I have crash due to some memory corruption caused by double-free: the first from protobuf.so and the second from protobuf-lite.so (see related bug).
I haven't access to top-lib2.so sources, and I can't link top-lib1.so with protobuf-lite.so due to my app functionality.
Thus my question is: how to deal with it?
I can't leave both due to this crash, I can't re-link my lib (top-lib1.so) with libprotobuf-lite.so, and I can't change top-lib2.so.
Is there any way to re-link top-lib2.so with libprotobuf.so without sources? Or is there any other possibility?
You do have a few choices.
The upstream bug you mentioned states that "libprotobuf.so has everything libprotobuf-lite.so has, and more". If that is indeed the case, one possible solution is to binary-patch top-lib2.so's .dynamic section to reference libprotobuf.so instead of the -lite.so. The former is shorter, so simply overwriting the string libprotobuf-lite.so with libprotobuf.so\0e.so is all you should need.
If you don't want to binary-patch top-lib2.so, you have other choices:
You could link in all of top-lib1.so comprising object files and all of libprotobuf.so ones into the main binary and hide all libprotobuf's symbols in it (via linker script). If you do that, top-lib2.so can't tell that there is anything except libprotobuf-lite.so which it expects.
You could do the same with top-lib1.so -- i.e. hide libprotobuf inside of it.
You could link your copy of libprotobuf.so with -Wl,--default-symver, which will append ##libprotobuf.so version to every symbol exported from libprotobuf.so, and avoid the symbol collision that causes the problem in the first place.

Why /lib/ld-linux.so.2 soname version bumps are so rare?

As far as I understand, "2" in "/lib/ld-linux.so.2" changes very rarely. There are old programs that can't work with new library and new programs that can't work with the old library. But they both refer to /lib/ld-linux.so.2, preventing installing both libraries.
BTW what are that version 'GLIBC_2.17' not found things? Why version is not in soname, but somewhere else?
Whenever a library is changed in a way that old programs do not work with the new version of the library this number is chaned. If old programs will still work with the newer library (and programs needing the new version will not cause a crash with the old library) there is no need to change the number because you can simply install the latest version of the library.
As far as I understand the "2" (it was "1" ten years ago) should not change any longer. The reason is simple:
The first version of "ld-linux.so.2" was written in a way that any version of "ld-linux.so.2" should work with any program using this file - maybe printing an error message when an older version of "ld-linux.so.2" is used.
This means: It is never necessary to install two different "ld-linux.so.2" files but it is enough to install the latest version of this file. You should not simply overwrite this file because it comes as a bundle with other files (e.g. "libc.so.6") that must have the same version.
In the "2" version of the loader .so files may contain a table of version numbers supported. So "libc.so.6", version GLIBC_2.16, may contain the information that "GLIBC_2.15" is also supported by this version of the library. (New versions should be backward compatible so this should be the case.)
Programs may contain a list of versions required (for example: a program requires libc.so.6 version "GLIBC_2.17"). The loader (ld-linux.so.2) checks if the library supports the version that is required by the program and refuses starting the program if not. In this case the error message form your question is printed by the loader.

What is the equivalent of forwarding DLLs in Linux/Unix?

I have a dynamic library that changes name across major versions i.e. version 3 was named lib3 and version 4 is named lib4, and so on.
I need to provide a shim lib3 that will allow an old application to use the new library in a transparent way, and most of the exported functions did not change across versions, so a forwarding DLL looks pretty good for the task on Windows.
Is there something equivalent on Linux/Unix?
The Linux equlivalent is rather easy. You can just use a symbolic link. For example, lib4 is the new library version, then you can create the following symbolic link:
ln -s lib4 lib3
Now, every time a program will need lib3 will automatically load lib4 as long as the interface
exported by the new version is equal to the old version, the program will not notice the difference.
I hope this helps. Let me know if you need more info.

Using library with different names within autoconf

I am trying to build an application with OpenSync 0.4 (0.3.9 indeed) dependency.
In the project's configure.ac the opensync library is written as libopensync1. However, this doesn't build on my Gentoo system. Changing libopensync1 to libopensync does fix the issue for me.
I searched with Google and found that libopensync1 is used in some distributions, while libopensync in others. So how to resolve this issue in configure.ac?
Thanks.
The macro AC_SEARCH_LIBS does what you need. (There is much heated debate about whether or not pkg-config should ever be used. If you choose to rely on it, ptomato gives a reasonable approach.) Simply add this to your configure.ac:
AC_SEARCH_LIBS([osync_mapping_new],[opensync1 opensync],[],
[AC_MSG_ERROR([can't find opensync])])
This will first look for a library named opensync1; if
it doesn't find that, it will look for opensync.
The primary drawback of using pkg-config is that most projects that
rely on it do not actually check if the data provided by the .pc
file is reliable, so configure may succeed but a subsequent build
will fail. It is always possible for a user to set PKG_CONFIG=true
when running configure and completely eliminate all of the data
provided by any associated .pc files, setting LIBS, CFLAGS, etc by
hand the 'old-fashioned' way.
The primary drawback of not using pkg-config is that the user
has to set LIBS, CFLAGS, etc. the old-fashioned way. In practice,
this is pretty trivial, and all pkg-config has done is move the
data from a single CONFIG_SITE file to separately maintained
.pc files for each package.
If you do use PKG_MODULE_CHECK, follow it up with a call to
AC_CHECK_LIB or AC_SEARCH_LIBS to validate the data in whatever
.pc file was located by PKG_CHECK_MODULES
I'm assuming that the place at which this occurs inside your configure.ac is inside a PKG_CHECK_MODULES call.
Looking at the libopensync sources, it seems that libopensync1 is the newer name, and libopensync is the old name. So, we'll use pkg-config macros to look for the newer name unless it doesn't exist.
Put this in your configure.ac:
# Check if libopensync1 is known to pkg-config, and if not, look for libopensync instead
PKG_CHECK_EXISTS([libopensync1], [OPENSYNC=libopensync1], [OPENSYNC=libopensync])
Then later in your PKG_CHECK_MODULES call, replace libopensync1 with $OPENSYNC.

Resources