Shared library not found - c

I am running Ubuntu 10.10 and a C program that uses a shared library libcrypto.so
When compiling it, though I have a Makefile that has the option -lcrypto, I get this message:
/usr/bin/ld: skipping incompatible ./libcrypto.so when searching for -lcrypto
/usr/bin/ld: cannot find -lcrypto
I did export the current directory before by doing:
export LD_LIBRARY_PATH=D_LIBRARY_PATH:.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
So what is wrong with my library and what can I do?

The first error message probably indicates that you have a 64-bit library but are doing a 32-bit compilation, or a 32-bit library but are doing a 64-bit compilation.
Run file libcrypto.so to see what type it is, then adjust your build (restart - remove all the object files) with either the option '-m32' or '-m64' to get the write build mode. If you can't work out how else to get that into the makefile, use:
make CC="gcc -m32" CXX="g++ -m32"
(or the 64-bit version if that's what you're after).

Could you post the output of this:
$ file ./libcrypto.so
And check that it is the right version for your machine? (I.e. 32 vs 64 bit, etc?)

Related

ld does not find secondary shared objects using ld.so.conf.d at compile time in Manjaro-Linux

I stumbled over a weird behavior of ld (compile time linking) in Manjaro-Linux.
Assuming I want to compile test.c which is dependent on libprimary.so and libprimary.so is dependent on libsecondary.so, which are installed in non standard paths.
I could compile like this (both are working):
gcc test.c -L/path/to/primaryLibDir -lprimary -L/path/to/secondaryLibDir -lsecondary -o test
or like this:
gcc test.c -L/path/to/primaryLibDir -lprimary -Wl,-rpath-link=/path/to/secondaryLibDir -o test
A look into ld manual under the -rpath-link option is telling that if -rpath-link is not used and the not directly dependent library is not given with -lsecondary, the file is (among other methods with higher prioriry tried before), also searched using the paths in /etc/ld.so.conf (priority 7).
I tried this in my Manjaro-Linux dsitribution and in the Ubuntu WSL.
And it works in all of them when writing the path directly into /etc/ld.so.conf.
If I write the path into a /etc/ld.so.conf.d/test.conf file (which is included via include /etc/ld.so.conf.d/*.conf in /etc/ld.so.conf) it works only in the Ubuntu WSL. In Manjaro Linux, it does not find the library anymore then.
Can anyone imagine, why this is not working? I think it must have something to do with the Manjaro setup.

Wrong ELF class with both 32 and 64bits lib

I am trying to solve a challenge by using LD_PRELOAD to load my own strcmp library.
I first tried to compile my library with gcc -shared -fPIC strcmp.c -o strcmp.so, but when I tried to execute my file with LD_PRELOAD=/path/to/lib/strcmp.so ltrace ./exec, I had a the error :
object '/path/strcmp.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS64): ignored
By comparing file /path/to/strcmp.so and file exec, I found out that my exec file was a ELF 32-bit LSB executable and that my lib was a ELF 64-bit LSB shared object.
Then I tried to compile my lib with gcc -m32 -shared -fPIC strcmp.c -o strcmp.so, but when executing I have the same error (but this time with ELFCLASS32) :
object '/path/strcmp.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored
Any suggestions? How can I have the same error with both 32 and 64 bits version of my lib?
As you noticed, if you have a single 32-bit shared library, you will get that warning when 64-bit programs are run. If you have a single 64-bit library, you get that warning when you run 32-binaries. We need your system to have both 32- and 64-bit versions of your libraries, and to allow the system to choose which one to use as needed. You can accomplish that with the following changes:
Compile both a 32-bit and 64-bit version of your library, and put them in /usr/lib and /usr/lib64 respectively on RedHat-based systems. Debian uses a different library naming scheme which unfortunately is not very consistent, so I'll leave it an exercise for the reader to determine the right place to put the two libraries on Debian systems.
Change your preload to remove all paths, like so: export LD_PRELOAD=strcmp.so This will allow the system to search only the correct library directory when it looks for a 32-bit or 64-bit library.
If you want to patch only one architecture, say 32-bit, then compile a 32-bit version of your library, and then compile an empty file into a 64-bit shared library of the same name. Place them both as described above.
Note that this only works if you use the system library directories. Even /usr/local/lib and /usr/local/lib64 are not allowed.
You should run 32-bit dynamic linker directly:
ltrace /lib/ld-linux.so.2 --preload /path/to/lib/strcmp.so ./exec

ld: warning: directory not found for option: -LC_ID_DYLIB=/usr/lib

I'm using OSX command line gcc and attempting to build a dynamic library. when I do the build I get the following warning. How is it it is not finding this library given /usr/lib is well known? And /usr/lib does indeed exist on my machine
this is what I am using:
gcc -arch i386 cata/*.c -dynamiclib -o build/cata.dylib -LC_ID_DYLIB=/usr/lib
Thanks
the way i solved it was to make it so the string that got stuck in the library (on where to find the library at runtime) was relative to nowhere -- if that makes sense. so it would be forced to use the LD_LOAD_PATH.
I was using the other flags because someone suggested I use them.
so the gcc i ended up using is this:
# my tree is like this
# cata/*.c
# build/*.dylib
#
cd build
gcc -arch i386 ../cata/*.c -dynamiclib -o cata.dylib
Doing this compiles/makes a library in the same directory where it thinks it is 'used' (basically having no path). I am now free to put it somewhere else. When it is later linked at compile time by a different program and then examined using
otool -L
it appears with no path in front of the library name. This is apparently preferable as now when the system goes to try to find it it resorts to looking at the standard libraries and eventually finds it (because I install it to one of the standard locations).
In the original way, otool -L was showing it having a required path of
'build/cata.dylib'
This made it un-findable and which is why i was trying to use the apple documentation to get around the problem.
This doesn't really solve why LC_ID_DYLIB doesn't work. I looked into the Loader.h file (line 643) and it has room for an identifier(0xd), a path, and a structure, so I don't really understand why my path wasn't getting picked up. but its two different topics. Loader.h is runtime and the other is gcc AFAIK. I'm still learning apple.

Gcc on OS X: Undefined symbols for architecture x86_64

I am writing an application that has multiple subdirectories. I have created a Makefile structure such that the subdirectories compile the file and do "ar rvs" and "ranlib libxxx.a" to create archives into the parent directory for linking.
However the "ld" command is running into the following problem.
ld: warning: ignoring file ./libxxx.a, file was built for archive which is not
the architecture being linked (x86_64):
./libxxx.a Undefined symbols for architecture x86_64:
I am using gcc on Mac OS X 10.10.1
I read many posts on this. I tried "gcc -arch i386", then I encounter the same error for i386
Undefined symbols for architecture i386:
I installed gcc-4.9.2 and tried using it instead of the default gcc, with no luck. I tried using x86_64-apple-darwin14.0.0-g++-4.9.2 and that did not help either.
The errors you are seeing mean that you have a mixture of i386 and x86_64 code in the build, and you need to be consistent. Unless there's a compelling reason to do otherwise (I'd be curious to know what it is), you should be compiling everything for 64-bit only. Using gcc on Mac, that is normally the default, but you can force it by adding a -m64 flag to the compilations. One way of doing that is to set CC="gcc -m64" on the make command line; there are other better ways too, but the details depend on your makefile contents.
To resolve: first, remove all the libraries and object code you've built in your project area (maybe make clean will do it — if you wrote a clean target). Then, fettle the value of CC or its flags (CFLAGS ultimately, but how CFLAGS is built depends on the makefile) so that 64-bit compilation is enforced. Then make sure you're using that in all compilations. If you don't see the -m64, you've got a problem.
If you must use 32-bit, substitute -m32 for -m64.
The discussion above assumes you are using gcc to run the ld command. If you are not, then you're on your own until you use gcc to run the ld command. In my view, you've got better things to do with your life than work out how to run the ld command correctly; I certainly have.

Cannot find -lagent when compiling c source code (incompatible library)

With gcc in ubuntu I used this command to compile my source code:
gcc 1.c -L. -lagent -lm -lpthread -o 1
but I got this error:
/usr/bin/ld: skipping incompatible ./libagent.so when searching for -lagent
/usr/bin/ld: cannot find -lagent
collect2: ld returned 1 exit status
How can I solve this?
The linker is telling you that the file ./libagent.so exists, but isn't in the appropriate format.
It could be an empty file, or built for 32-bit instead of 64-bit, or it could be a symlink pointing to the wrong version.
Let's look at your command line parameters first.
gcc 1.c -L. -lagent -lm -lpthread -o 1
You call the compiler gcc with the input source code of 1.c and then you specify an additional (link) library path to include the current directory (.) -L.. Then you tell it to link against the agent and pthread libraries, where shared (dynamic) libraries have the default name format of libNAME.so where NAME is replaced with the name. Static libraries have the default file extension .a (from the term archive). Then you specify the output (executable in this case) to be the file 1 (digit one, not the letter 'ell').
/usr/bin/ld: skipping incompatible ./libagent.so when searching for -lagent
This is the linker (ld) telling you that the file ./libagent.so (it found presumably in the current directory) is not a valid shared library format as it was expecting. This could be for a different machine architecture (x86-64, ARMle, PowerPC, MIPS) or a incompatible library format (I don't know if library files, .so, have any COFF or ELF or PE dependencies or not). Or simply otherwise empty or corrupted (e.g. interrupted output due to errors compiling / linking).
So you normally want to not include your current directory in your linker's search path, unless you have the copy of the library that you have not yet installed (typically to /usr/lib/ or /usr/local/lib/), such as you wrote the library and wish to link test programs to it before you install it.
Debian and Unbuntu-oriented part of the answer:
Normally you want to install shared library's runtime component (often named something like libagent) and the associated development files (most often at least a header file and hopefully a manpage) in the format libagent-dev. RPM based Linux systems use libagent-devel style naming conventions (from memory). So sudo aptitude install libagent-dev should do the trick if that is the package's name.

Resources