I'm creating an optimized embedded linux system for two different ARM boards, A RaspberryPi and a Gumstix Overo, both of which are using eglibc-2.16 for the GNU C library. But, I've noticed that my libc.so library for the RaspberryPi has ruserok, ruserok_af & iuserok symbols from the inet lib, but the libc.so library for my Gumstix Overo board doesn't contains those symbols.
I looked at the configure help output to see if I was missing a switch to include those symbols, but nothing jumped out at me. Is there something special that I need to do to that I'm overlooking to get the inet library and all of its symbols compiled into libc.so?
I fixed this problem by reconfiguring my OpenEmbedded build environment.
Related
I am doing some research whether to compile C++ libraries static or dynamic for a new project. (I have read this answer, also). I saw that on OpenBSD and FreeBSD the system libraries are a lot bigger (5-7 MB) than on Linux (1.5 MB) because they are not stripped. So I have 2 questions:
The OpenBSD libestdc++.so is any different than libstdc++.so? I didn't find any info on it, google just corrects me, removing the "e" letter from the word.
Why these libraries are so big on BSD? If I would like to deploy or statically link them they will be huge. Is there a workaround for this?
Thank you.
On OpenBSD, libstdc++ is the base c++ library (GCC 4.2), libestdc++ is installed from ports (GCC 4.9 or 6). The libraries are installed with symbols on OpenBSD, you can strip the symbols with strip -s libwhatever.so.
Say I have a C++ binary that was compiled with a version of gcc say 4.4.x, which is used on a client linux box.
If I want to upgrade my compiler to use a newer one, say 4.9.3 (because I want to use C++11):
What kind of things would need to be upgraded on the client box to run this new binary? (e.g. .so libraries)
And how would one find this out?
What kind of things would need to be upgraded on the client box to run this new binary?
You will need to ship two shared libraries with your application: libgcc_s and libstdc++. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html for more details.
You can ship these libraries in the same directory with your executables if you link using $ORIGIN. See https://stackoverflow.com/a/4742034/412080 for more details.
And how would one find this out?
Run ldd and readelf -d on your executables to see what libraries they need.
I'm guessing from the fact that you mention GCC 3.4 that your client system is running RedHat/CentOS/Scientific Linux 4 which is so old that even Red Hat ended support for it three years ago. If you were running any newer version then you would have been able to take advantage of the Developer Toolsets which include a modified version of GCC that statically links newer parts of the standard library into your binary so that it can run on legacy systems without newer glibc/libstdc++ runtimes.
There are two mechanisms to test compatibility of shared libraries:
The SONAME: a canonical name for the library that is used by the linker to reference the library. You can query the list of required libraries for every ELF object (executable or library) with the ldd command, and you need to do this recursively for each referenced library to get a full list of libraries needed.
The symbol version information. This is an additional constraint that allows adding functionality to existing libraries by introducing version requirements per symbol used -- a program only using symbols that have existed for ages will require a lower minimum version of the library than one that uses new functionality.
Both of these need to be fulfilled in order for the program to run.
The typical approach of Linux distributions is to keep a mapping of SONAME to package name (as multiple versions differing in SONAME can be installed concurrently), and a table of versioned symbols to the package revision these were introduced. The appropriate package development tools for your distribution should be able to create a list of dependency specifications that matches your program's requirements; if they fail to do so because symbols are unknown, it is likely that this version cannot be supported on that release of the distribution.
An alternative could be to link statically all libraries (notably libstdc++) other than the libc (and libm and libdl if you use them); then the produced ELF executable depends only of the libc; however, with ancient enough kernels or libc (on the target machine) even that might fail to work...
For details, read Drepper's paper: How To Write Shared Libraries
I have a C++/C application which needs to be compiled as a 32 bit application (as there are certain third-party libraries only available for 32 bit). However, the compilation as well as the execution will happen on CentOS 6.4 x86_64 machine.
I am using gnu autotools for building. After doing a lot of googling, finally figured a sets of options to give to ./configure to create 32 bit executables/shared objects. Set the LD_LIBRARY_PATH to search in /lib, /usr/lib/, /usr/lib/gcc/... instead of /lib64, ... Verified that all the generated .so and executable are 32 bit by using file command.
But I get the error: "undefined symbol: _ZL22__gthrw_pthread_cancelm" if I run the executable.
Any clues?
It seems you forgot to link to pthreads with -lpthread.
GCC adds a layer of abstraction over pthreads and this abstraction use weak symbols, so you can build your executable without link error but fail at runtime.
Is there a 32bits pthread library on your target host? If not, I guess you need to get one installed. Also inspect the output of ldd <my-program> on your target host, this might help you find out what is missing.
I have built an app on Ubuntu 12.04 and have tried running it on an embedded system. I ran apt-cache show libc6 on my dev machine which shows (amongst other things)
Package: libc6
Priority: required
Section: libs
Architecture: i386
Source: eglibc
Version: 2.15-0ubuntu10
Replaces: belocs-locales-bin, libc6-i386
Provides: glibc-2.13-1, libc6-i686
The version of libc6 that exists on the embedded device is 2.8.90. In the \lib directory on the device I have 2 libs
libc-2.8.90.so
libc.so.6
When I copy my application onto the embedded device I get the following errors
/usr/lib/libc.so.6: version `GLIBC_2.15` not found (required by ./ServerSocketApp)
I know that if possible I when I build the application on my dev maching I need to force it to link to the same version of libc6 as exists on the embedded device. The problem I have is that I simply do not know how to do this. Any answers that I have found are meaningless to me right now. Is there some option that I need to pass to g++ to get this to link to version 2.8.90 ??
In desperation I am thinking is it possible to copy the libc on my dev machine onto the embedded device in place of what is there already and hope for the best??? I just cannot seem to find any documentation online that explains in simple terms how you even go about this so any advice at all would be really really welcome as I am tearing my hair out here.
OK, here is a somewhat longer explanation, but proceed with care. I still strongly recommend that you setup a chrooted environment to match the one available on the embedded device and use it during the last stage of your build process.
You should understand how dynamically linked ELF executables are loaded and executed. There is something called the run-time link editor (RTLD), also known as the dynamic linker, that takes care of loading all the necessary dynamically linked libraries, fixing relocations and so on. The name of the dynamic linker is /lib/ld-linux.so.2 on 32-bit Linux systems with glibc2 and /lib64/ld-linux-x86-64.so.2 on 64-bit Linux systems with
glibc2. The dynamic linker is very tightly coupled to the glibc2 library and usually can only handle the matching version of that library. Also the path to it is hardcoded into the executable by the linker (usually ld, implicitly called by the compiler to do the linking). You can easily check the validty of the last statement by simply doing ldd some_elf_executable - the run-time link editor shows up with the full path:
$ ldd some_elf_executable
linux-vdso.so.1 => (0x00007fffab59e000)
libm.so.6 => /lib64/libm.so.6 (0x0000003648400000)
libc.so.6 => /lib64/libc.so.6 (0x0000003648800000)
/lib64/ld-linux-x86-64.so.2 (0x0000003648000000) <--- the RTLD
In order to produce a dynamically linked executable that uses a version of glibc2 different from the one installed on the system, where the executable is to be run, you should link your code with the following set of options to ld:
-rpath=/path/to/newer/libs - this one instructs the dynamic linker to first search /path/to/newer/libs when trying to resolve library dependencies. /path/to/newer/libs should match the path where you have copied the newer glibc2 version on the embedded device
-rpath-link=/path/to/newer/libs - this option instructs the linker (not the dynamic linker) to use /path/to/newer/libs when resolving dependencies between shared libraries during link time - this should not be normally necessary in your case
--dynamic-linker=/path/to/newer/libs/ld-linux.so.2 - this one overrides the path to the RTLD that gets embedded into the executable
The way to provide those options to ld is usually via the -Wl option of GCC.
-rpath=/path/to/newer/libs
becomes:
-Wl,-rpath,/path/to/newer/libs
(notice that the = is replaced by ,)
--dynamic-linker=/path/to/newer/libs/ld-linux.so.2
becomes:
-Wl,--dynamic-linker,/path/to/newer/libs/ld-linux.so.2
You should copy /lib/ld-linux.so.2 from your development system to /path/to/newer/libs/ on the embedded device. You should also copy libc.so.6, the mathematical library libm.so.6 and all the other libraries that are used by the executable or that might get loaded indirectly. Note that libc.so.6 and libm.so.6 are actually symbolic links to the real libraries which have names like libc-2.<version>.so. You should copy those library files and create the appropriate symbolic links to make everybody happy.
This is fundamentally incorrect. While you may be able to hack together a way to link in the old libc, the problem is your environment setup.
When you develop applications for an embedded system. You do so on a host. Generally, the host and embedded device are not on the same architecture. For example, your host is usually a desktop/laptop running on an x86 and the embedded system might be on an ARM. If you happen to be on the same architecture as your embedded device, that is sheer coincidence. Standard practice environment setup should still follow:
The host machine should have a tool chain setup to cross build applications to the embedded architecture
The host machine should have a copy of the full rootfs that exists your embedded device. This will contain all of the libraries that your cross tools will use to compile applications for the embedded system
If you have it setup this way. Development will be easy. You will be able to setup simple, clean make files to build your applications and then just scp the binaries over to the embedded system and run.
You might have some luck compiling with the LSB SDK (http://www.linuxfoundation.org/collaborate/workgroups/lsb/download) which restricts the symbols available to the executable.
According to the LSB scanner, my binary is supposedly incompatible with a specific version of Linux because it uses GBLICXX_3.4.9 symbols. But when I tried to run the binary myself on that version, everything seems to work fine...
Can a binary even start on a Linux distro if that distro is missing the runtime libraries containing the required symbols?
I don't know if I've understood well the question but as far as I know even though you have compiled your program with a modern glibc does not necessarily mean that you won't be able to execute into an older version. The next Linux command:
objdump -T "your exe or lib file" | grep GLIB
will show you which version of the glibc the symbols of your program belong to.
For further information there is a paper called How to write shared libraries by Ulrich Drepper that explains a lot of things of how symbols work in linux not only for shared libraries but also for executables
I suspect they're warning you that you're using symbols that, even if they are available on your test system, may not be available on all LSB-compliant systems.