Running ELF file with version mismatch of shared object file - dll

I have an ELF file that links to a shared object file from version X of a library. I only have access to the version of the shared object file from version Y of the library. When I try to run the ELF file, I get <ELF filename>: <shared object filename>: version X not found (required by <ELF filename>). Installing version Y of the library is not an option for me right now. Is there any way to force the ELF file to ignore the version mismatch and try to run? Can I fool the ELF file or somehow edit the shared object file to change the apparent version?

No. The "version" is not the version of the library, but the version of the symbol (ELF files support symbol versioning for keeping backward binary compatibility when changing APIs, see this post for details).
Effectively what it's saying to you is that it's missing a symbol (function, constant, global, etc.) that is not present in the library you have. Which means the library does not have the interface it needs.

Related

How find_library does handle so version numbers?

How does CMake's find_library handle so version numbers like in "libFOO.so.3.2"? Some libraries have symbolic links from libFOO.so to the right version, some do not.
Does CMake find a library without the symbolic link when I just use find_library(NAMES FOO)?
What should I do to help CMake figuring out the right library?
Assuming a linux distribution, the system package manager will generally provide runtime packages and development packages. If you have installed the development package for a library (e.g. libFOO-dev), it will generally include the following three files in your /usr/lib or /usr/local/lib
libFOO.so.3.2.0 (the versioned binary)
libFOO.so.3 (soname = symlink to versioned binary)
libFOO.so (namelink = symlink to soname)
The namelink has no version details in the file name. This will be used to find the library by linker command line option, e.g. -lFOO
You should use the namelink (e.g. FOO) in the find_library cmake command.
The linker will embed the soname file into your binary.
If you have multiple versions of the library installed, be sure to symlink the namelink file to the soname file that you want to use. This is really only an issue if you have multiple major versions of the same library installed. Within a major version, APIs should be backwards compatible.
In addition to #marksisson's answer:
In case you download an SDK as a zip archive with such symlinked .so files it may happen that the symlinks are broken. Instead of real symlinks you have small text files containing the names of the linked files. As a consequence the linker complains about an unrecognizable file format.
To fix that, just recreate the symlinks after unpacking the zip file.

CMAKE - runtime library hidden files

I am running Linux Redhat, I have Anaconda installed and I am trying to install a program (libspimage) using CMAKE amd I get the following warning/error:
CMake Warning at src/CMakeLists.txt:74 (ADD_LIBRARY):
Cannot generate a safe runtime search path for target _spimage_pybackend
because files in some directories may conflict with libraries in implicit
directories:
runtime library [libtiff.so.5] in /usr/lib64 may be hidden by files in:
/home/michantia/anaconda2/lib
Some of these libraries may not be found correctly.
When I do:
echo $PATH
I get:
/home/mi_a/anaconda2/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/michantia/.local/bin:/home/michantia/bin
I tried:
export PATH=/usr/lib64:$PATH
hoping cmake would find the libraries in this directory before finding them in anancoda's, but that did not work. I also tried two other similar suggestions for a similar problem that I saw in stackoverflow, but that did not work.
Any other ideas are highly welcomed.
Warning message
Cannot generate a safe runtime search path for target
is related neither with CMake ability to find a library (libtiff.so.5 in your case) nor with a linker ability to link the library.
The warning message means that when a target (_spimage_pybackend) will be loaded, the loader will be unable to choose the correct library: according to the loader's algorithm and the target's setting, file /home/michantia/anaconda2/lib/libtiff.so.5 will be choosen instead of proper one /usr/lib64/libtiff.so.5.
The error is usually resulted in linking into the single target two libraries from different directories, when the directory with a second library also contains a file with the name of the first library:
Directory /usr/lib64 contains a library libtiff.so.5, which is linked into the target.
Directory /home/michantia/anaconda2/lib contains a library <A> which is also linked into the target; but this directory also contains a file libtiff.so.5.
According to CMake algorithm, runpath for the binary file of such target will include both directories, so both libraries could be found. But such runpath confuses the loader to find the first library properly.
Except from avoiding such situation (when a library is contained in two directories), one hardly is able to handle this warning.

Use CMake find_package with a custom, bugfixed file

I have a library (namely CGAL). It provides a FindMODULE.cmake file for a third-party library not shipped with it CGAL (namely Intel TBB). Unfortunately, this file has a bug that I need to fix. (The bug seems to be related to incompatible directory structures, but that's not the point here.)
So the CMakeLists.txt of my project has a line:
find_package( TBB )
This will invoke FindTBB.cmake which is provided in the directory structure of CGAL.
Now, I need to fix a bug in FindTBB.cmake. I'd like to just copy that file and put the fixed version directly into my project directory.
How can I tell CMake to use FindTBB.cmake in my project directory (instead of the one provided by CGAL) when calling find_package?
Alternative approach:
Copy the file to your module directory and modify it.
Call find_package(TBB) before you do anything related to CGAL.
Use the CMake call used to find / interact with CGAL. If you are lucky, the results of all checks are cached and it work. It still might not work, depending on what is actually done.
The find_package function might be too heavy in this case, you can try just including your relocated .cmake file like this.
include(<local path>/FindTBB.cmake)

Can the object file name be changed from .obj during cmake compiler testing?

Ultimately, I'm trying to build Apache QPID to run in the HPE NonStop OSS environment (a Posix-like environment on the NonStop system). The latest version of QPID uses cmake to build so I first need to get cmake to work for that environment. My earlier attempts tried to build in OSS directly (I needed to build cmake first before trying to build QPID), but I ran into many problems there. So lately I'm trying to build in Windows using a set of cross-development tools (compilers etc.) for NonStop. I've downloaded a Windows version of cmake 2.8 (suggested by the QPID build instructions) and am trying to use that with the X-dev tools to build QPID for OSS.
One big issue I've run into has to do with how cmake does things to test compilers and so forth early on. It will invoke the compiler to create an intermediate object file from C (and/or C++) source file and after that it will invoke the compiler to link an object file from the intermediate file. It seems that cmake prefers to add .obj to file names to create the intermediate object file name. This will work OK with my cross-compiler when creating the file (the name passed with -o to the compiler) but it will not work when passing this name for link purposes. Here is a short bit of the output per the CMakeError.log file (from trying build an OSS version of cmake 2.8 itself):
Determining if the C compiler works failed with the following output:
Change Dir: C:/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp
Run Build Command:C:/cygwin/bin/make.exe "cmTryCompileExec/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
make[1]: Entering directory '/cygdrive/c/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp'
"C:/Program Files (x86)/CMake 2.8/bin/cmake.exe" -E cmake_progress_report C:/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj
/cygdrive/c/NonStop/tndm_cmplrs-j20/usr/bin/c89.exe -o CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj -c C:/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec
/cygdrive/c/NonStop/tndm_cmplrs-j20/usr/bin/c89.exe "CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj" -o cmTryCompileExec
c89.exe: error: Invalid input file extension"CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj".
The cross-compiler fails because it requires intermediate object files to use .o for the extension, in order to determine they are intermediate object files. There is no way to get the c89 compiler to recognize testCCompiler.c.obj as a file type it knows what to do with.
So I've been searching (trying to find a local expert, but no one in my organization knows cmake; also numerous Google searches but could not find an answer) to see if there is any way to get cmake to change the name of the output file it uses for these type of compiles and tests. I've found info and then set CMAKE_C_OUTPUT_EXTENSION in a toolchain file:
SET(CMAKE_C_OUTPUT_EXTENSION ".o")
but that has made no difference.
If I can find a way to get cmake to create object files with names like testCCompiler.c.o instead of testCCompiler.c.obj, then the c89 cross-compiler would work.
Is it possible to do this?
UPDATE: I've managed to figure out that setting CMAKE_C_OUTPUT_EXTENSION in the toolchain file doesn't help. This gets overwritten in the CMakeCInformation.cmake (depending on whether UNIX is set or not). I also tracked down that UNIX gets set to true in Platform/UnixPaths.cmake, which gets INCLUDEd by various Platform files. So I've created a Modules/Platform/OSS.cmake file which includes it to takes care of that. I'll probably need/want to add other settings there later as I determine more flags for compilers etc that should be set to specific values for the OSS environment.

Adding a shared library and executable, compiling source files twice

gcc (GCC) 4.7.2
cmake version 2.8.11
Hello,
I wondering if there is a way around the following issue. I have highlighted below:
SET(GW_SOURCE_FILES
module.c
module_imp.c
module_message.c
module_config.c
module_queue.c)
# Compiles the source files to create the shared library called dlg_gw.so
ADD_LIBRARY(dlg_gw SHARED ${GW_SOURCE_FILES})
# Link additional libraries to this
TARGET_LINK_LIBRARIES(dlg_gw gc srl ${APRUTIL})
# ISSUE: Now I want to create my executable using the same source files. module.c is where my 'void main(void)' is.
# However, I have some functions in there which will also be part of the library.
# However, this will recompile the same source files all over again. I don't really like that behaviour.
ADD_EXECUTABLE(sun_gw ${GW_SOURCE_FILES})
# After the executable is created, link the libraries with it.
TARGET_LINK_LIBRARIES(sun_gw ${APR} driver dlg_gw dlg_sip dlg_ss7 dlg_isdn)
I hope you can see the issue above, as I am compiling the same source files twice. Once to create the dlg_gw library. Then again to create the executable sun_gw.
I was thinking of taking out the 'void main(void)' and putting it in a new file called runtime.c and then doing the following:
ADD_EXECUTABLE(sun_gw runtime.c)
But the above require me to change some of the source code.
Many thanks for any other suggestions,
The "OBJECT" library type introduced in CMake 2.8.8 can be used to avoid repetitive build of same files.
See http://www.cmake.org/Wiki/CMake/Tutorials/Object_Library