What can interfere with library load path - c

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.

Related

The Linux kernels 3.* series won't boot properly upon being customly compiled in Ubuntu 16.04.1 by means of make-kpkg and gcc-4.8.5

Recently I upgraded up to Ubuntu 16.04.1 Xenial (from 14.04 Trusty) the build-host where I've compiled different linux kernels so far for my own project. Ubuntu 16.04.1 implies using a new updated environment for building binaries. These tools include a new gcc-5.4, libc6 (for userspace applications), etc. Also a new Ubuntu supplies (or suggests) a new kernel-package containing a new make-kpkg script and pulling different dependencies like build-essential, binutils, etc. with it
Ok, my task is to compile a linux kernel v3.10.12 (or v3.19) and run it within a VirtualBox machine (architecture x86_64, system Ubuntu 16.04.1). I used to be able to compile kernel-v3.10.12 and kernel-v3.19 in Ubuntu 14.04 Trusty deployed on the build server with the compiler gcc-4.8 and launch the kernels under the VirtualBox machine I mentioned above, but now something goes wrong while starting a kernel compiled
For example, let's consider v3.10.12 being compiled and run
For building the kernel I utilize 'make-kpkg' script provided by Ubuntu aptitude's package 'kernel-package'. I build the kernel for x86_64 using gcc-4.8 as I have always been doing
Once 'make-kpkg' has compiled the kernel and gathered linux-headers it starts packing them into deb-packages what makes me able to execute 'dpkg -i' on them in the system and install them in a 'debian' way
Okey, supposing I did it. Then I am going to reboot the system
When I choose my compiled kernel in the grub menu, it writes in the screen "Loading linux kernel... Loading initial ramdisk", then the inscription disappears, the screen goes black and I see only a cursor in the form of underscore "_" sign in the top-left side of the screen. That's all. Nothing is going to happen further. The booting process seems to have stuck
I tried swapping make-kpkg for an old one (from Trusty), swapping compiler gcc-4.8.5 for gcc-4.9, gcc-4.7, even gcc-5.2 having made a couple of supplementations inside the directory include/linux/ for the support of gcc-5.2, but nothing has come off, the result still persists being the same
I tried the same actions (on the same Ubuntu 16.04.1 and tool-chain) with new kernels 4. series* (for example, 4.6) meaning building the kernels, packing them into *.deb packages and installing into the VirtualBox machine and rebooting the system, and everything goes correctly, I see debug messages in the screen like I have always seen. I tried to use gcc-4.7, gcc-4.8, gcc-4.9, gcc-5.4 and everything works, I am able to load the linux-kernel-v4.6 appropriately and completely. But when I build 3.10.12 (or 3.19) kernels I cannot boot them properly and cannot have figured out why it has been happening
Actually, what I have found out is that the deal is in the kernel but not in initrd because I managed to substitute the 'broken' kernel by a working one having left 'initrd' built together with the 'broken' kernel and the debug logging started appearing and the kernel was loading until a rootfs came out to be mounted, at that moment the kernel didn't manage to load it and left in initramfs mode
Has someone faced the same issue I am observing? Actually I am almost exhausted having been struggling with this trouble for days
Maybe someone has any recipes or suggestion how to get rid of the problem?
I even put the 'panic' function code exactly in the first line of the function "asmlinkage void __init start_kernel(void)" but nothing happened, still the same black screen
Can the problem be related to a new glibc being used by gcc compiling my kernel? Personally, I am not prone to think so but in the world of linux everything can happen. On the other hand maybe toolchain (ld, as) somehow has affected? I am kindly asking to provide me a help.
I am nearly assured that someone before me has already encountered such an issue, I would have been searching for a topic alike but didn't find anything resembling
Thank you in advance
Short Answer
It's a glibc kernel version mismatch, if you need this you could create the glibc package such that it supports the kernel version that you need, by using the --enable-kernel flag at configuration time.
Long Answer
It's highly likely that your glibc was compiled in such a way that it only works down to a certain version of linux. This is done with the help of the --enable-kernel flag at the configuration stage. Any version older than the one specified in --enable-kernel will be rejected by glibc as a consequence no program will ever be loaded, like the init program presumably systemd's init.
This is from the configuration help of glibc
--enable-kernel=version
This option is currently only
useful on GNU/Linux systems. The version parameter should have the form X.Y.Z and describes the smallest version of the Linux kernel the generated library is expected to support. The higher the version number is, the less compatibility code is added, and the faster the code gets.
Finally I succeeded in this problem
Actually what I have done is to have compiled an old gcc-4.8.5 with an old glibc-2.19 on the host-system where I build the old-versioned kernels.
Glibc-2.19 was compiled with an option --enable-kernel=3.10.12 and with headers of an old-versioned linux-3.10.12. The compiler has turned out to be like a 'cross-compiler' with usage of glibc-2.19. So, I built an old kernel with the version 3.10.12 with this 'cross-compiler', which uses glibc-2.19, and everything has started working in a proper way
Thanks for the help and directing me to a right way to solve the problem, but I am obliged to notice that the deal was in host-system's glibc used but not in target-system glibc used as I had been assumedly said (but maybe I misunderstood #iharob)

How to install xsock?

I downloaded library from http://sourceforge.net/projects/xsock/.
In INSTALL file are steps to run this libs.
I changed location to xsock/libxsock and type in terminal ./configure
Nothing happend... How to solve this?
cd' to the directory containing the package's source code and type
./configure' to configure the package for your system. If you're
using csh' on an old version of System V, you might need to type
sh ./configure' instead to prevent csh' from trying to execute
configure' itself.
Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for.
Type `make' to compile the package.
...
4...
The library is broken, and cannot be built as distributed. A number of autoconf/automake files are missing from the archive.
Given that the library appears to have been primarily developed on Windows systems, it seems likely to me that the UNIX parts of the build process for this library have not been maintained, or may never have worked at all. My recommendation is that you find another library — this one seems to be largely unmaintained, and the code quality seems rather low.

How can I compile a Linux executable for a different machine?

I've written a Linux program in C, and I'm trying to get it to run on a server system. It looks like everything should work, but when I try it, I get this:
/lib64/libc.so.6: version `GLIBC_2.14' not found (required by <program>)
/lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./libdbi.so.1)
(Where <program> is my program's name.)
So far as I can tell, my program only requires that version of GLIBC because libdbi does. I've tried compiling libdbi from source, and it still attempts to link to that version of GLIBC.
I don't own the server system (it's a shared system I run a website on, and have SSH access to), so I can't make any changes to it -- that's why the library file is in the same directory, and I've set LD_LIBRARY_PATH=.. Unfortunately I also don't have access to a compiler on it -- when I try to run GCC, I'm told "permission denied". It's run by a big corporation, and I'm only one customer; the chances of them making any changes at my request are essentially zero.
Is there any way to compile the program on my system so that it will work on the server?
Before I asked, I found these similar questions:
Compile C program in Linux with different glibc library: the link in the answer goes to a 404 page, and from what I've been able to determine, apgcc isn't available on Debian distributions.
Relink a shared library to a different version of libc: seems to say that this problem doesn't exist, because "glibc tend to be backwards compatible" (except they apparently aren't in this case).
How to compile Linux C program to run on another Linux machine?: suggests a chroot or virtual machine, which I've done before elsewhere, but how can I tell it to use a libc without that old GLIBC version?
is binary executable file portable: suggests static-linking, but libdbi dynamically-links to its driver files, so that apparently can't be done -- I get several errors referring to missing functions like ldopen.
There are others, but they seem to be variations on those.
I'd be willing to use a non-free solution (like one that I saw in another answer I can't find now) if I turn this into a commercial product, but for a single use it seems like massive overkill, not to mention the expense.
Is there any way to simply tell libdbi to link to a later GLIBC version, maybe? If not, is there any solution I've overlooked?
Big corporation or not, the least they owe you if you are paying for service in any way or being paid for development to meet a requirement is a careful description of the runtime environment so you can duplicate it on a development machine.
Then you must set out to systematically duplicate this environment. Since you're using libdbi you should be thorough. Database connections can exercise big chunks of the system API, so you want to have exactly the same version of Linux, gcc (even if you can't run it, you need to know the version other parts of the system were compiled with), and other tools and libraries. If you don't, you won't be able to have much confidence that your development machine tests translate to good behavior on the target.
A virtual machine is a good way to create a specialized development environment without messing up your existing one.
You must compile it on a machine that has the same version of glibc as the target machine, or an older version. shared library compatibility works in that direction only.
Find out what version of Linux the server uses, get a copy of it and install it in a VM
Virtualbox is good for this
You can use this environment for testing code as well as this particular compilation problem
You have the following options:
Compile your code on the server machine (which likely has gcc installed)
Compile your program with statically linked libraries (option -static for gcc)

What is the point of using `-L` when there is `LD_LIBRARY_PATH`?

After reading this question, my first reaction was that the user is not seeing the error because he specifies the location of the library with -L.
However, apparently, the -L option only influences where the linker looks, and has no influence over where the loader looks when you try to run the compiled application.
My question then is what's the point of -L? Since you won't be able to run your binary unless you have the proper directories in LD_LIBRARY_PATH anyway, why not just put them there in the first place, and drop the -L, since the linker looks in LD_LIBRARY_PATH automatically?
It might be the case that you are cross-compiling and the linker is targeting a system other than your own. For instance, MinGW can be used to compile Windows binaries on Linux. Here -L will point to the DLLs needed for linking and LD_LIBRARY_PATH will point to any libraries needed by linker to run. This allows compiling and linking of different architectures, OS ABIs, or processor types.
It's also helpful when trying to build special targets. I might be case that one links a static version of program against a different static library. This is the first step in Linux From Scratch, where one creates a separate mini-environment on the main system to become a chroot jail.
Setting LD_LIBRARY_PATH will affect all the commands you run to build your code (including the compiler itself).
That's not desirable in general (e.g. you might not want your compiler to run debug/instrumented libraries while it compiles - it might even go as far as breaking your compiles).
Use -L to tell the compiler where to look, LD_LIBRARY_PATH to influence runtime linking.
Building the binary and running the binary are two completely independent and unrelated processes. You seem to suggest that the running environment should affect the building environment, i.e. you seem to be making an assumption that the code build in some setup (account, machine) will be later run in the same setup. I find this assumption rather strange. I'd even say that in most cases the building and the running are done in different environments. I would actually prefer my compilers not to derive any assumptions about future running environment from the environment these compilers are invoked in. Looking onto the LD_LIBRARY_PATH of the building environment would be a major no-no.
The other answers are all good, but one nobody has mentioned yet is static libraries. Most of the time when you use -L it's with a static library built locally in your build tree that you don't intent to install, and it has nothing to do with LD_LIBRARY_PATH.
Compilers on Solaris support the -R /runtime/path/to/some/libs that adds to the path where libraries are to be searched by the run-time linker. On Linux the same could be achieved with -Wl,-rpath,/runtime/path/to/some/libs. It passes the -rpath /runtime/path/to/some/libs option to ld. GNU ld also supports the -R /path/to/libs for compatibility with other ELF linkers but this should be avoided as -R is normally used to specify symbol files to GNU ld.

How to tell whether an executable was compiled for the present machine?

I have some c code that I compile and run, in a directory that is accessible from many different unix computers (various linux and mac, occasionally others), with different OS's obviously needing different executables.
I have a simple shell script that invokes the appropriate executable, prog.$OSTYPE.$MACHTYPE, compiling it first if necessary. This is very simple (although it requires using csh in order to have $OSTYPE and $MACHTYPE be reliably defined) and it almost works.
However, it turns out that even $OSTYPE and $MACHTYPE are not enough: for example, compiling on OSX 10.5 yields an executable prog.darwin.i386 which, when invoked on OSX 10.4, crashes instantly.
Yes, recompiling every time I want to run the program is one way to solve this, but it seems excessive. I know having a bin directory on every machine is a standard solution, but a non-root user may not have much write access outside their home directory (which is common to all the machines).
So my question is, is there a better approach? The compiler (often gcc) obviously knows what kind of system it is compiling for -- is there a good portable way to find out what "kind of system" my script is running on, so it can invoke the correct executable, instead of one with undefined behavior?
You could use gcc -v to figure out what the installed/runnable gcc thinks is the target arch for hosted compiling (something like $(gcc -v 2>&1 | grep Target: | sed 's/.*: *//') in bash)
edit
If you really want to be able to do this without having anything in particular installed, you could extract the config.guess script from gcc (its in the top level directory of any gcc source package) and run that. Unfortunately this won't work for all systems and might not exactly match what the system gcc package uses for some distributions, but this is the script used to configure gcc for building unless you explicitly override it...
try to use file command from shell prompt
Download some open source packages written in C and have a look at the file ./configure which is basically a large shell script that collects info from many sources, often by compiling and running short C programs. This will tell you everything that you need to know.
Since you are dealing with recent Mac OS X make sure you choose a package that is currently being maintained and supports OS X versions.

Resources