Use NPTL while keeping glibc with linuxthreads - linux

I would like to know if it is possible to test a specific binary with nptl instead of linuxthreads which is embedded in my glibc. I don't want to recompile the glibc because it is the one provided with my specific hardware/software and I don't want to break everything. I just want to be able to test this implementation and to see what could be the gain
Thanks in advance

I don't want to recompile the glibc
If your glibc was compiled with linuxthreads, and not nptl, then obviously you can't use it to test a binary with nptl.
Your choices are:
Use some other (newer) system that has nptl-enabled glibc, or
Build a separate nptl-enabled version of glibc, and use it, e.g.
cd glibc-2.15
./configure --prefix=/usr/glibc-nptl && make && sudo make install
# now run the binary using newly-built glibc:
/usr/glibc-nptl/lib/ld-2.15.so /path/to/binary
See also this answer.

Related

Build and bind against older libc version

I have dependencies in my code that requires libc. When building (cargo build --release) on Ubuntu 20.04 (glibc 2.31) the resulting executable doesn't run on CentOS 7 (glibc 2.17). It throws an error saying it requires GLIBC 2.18.
When build the same code on CentOS 7 the resulting executable runs on CentOS 7 and Ubuntu 20.04.
Is there a way to control which GLIBC version is required to build this version on Ubuntu 20.04 too?
If your project does not depend on any native libraries, then probably the easiest way would be to use the x86_64-unknown-linux-musl target.
This target statically links against MUSL Libc rather than dynamically linking against the system's libc. As a result it produces completely static binaries which should run on a wide range of systems.
To install this target:
rustup target add x86_64-unknown-linux-musl
To build your project using this target:
cargo build --target x86_64-unknown-linux-musl
See the edition guide for more details.
If you are using any non-rust libraries it becomes more difficult, because they may be dynamically linked and may in turn depend on the system libc. In that case you would either need to statically link the external libraries (assuming that is even possible, and that the libraries you are using will work with MUSL libc), or make different builds for each platform you want to target.
If you end up having to make different builds for each platform, a docker container would be the easiest way to achieve that.
Try cross.
Install it globally:
cargo install cross
Then build your project with it:
cross build --target x86_64-unknown-linux-gnu --release
cross take the same arguments as cargo but you have to specify a target explicitly. Also, the build directory is always target/{TARGET}/(debug|release), not target/(debug|release)
cross uses docker images prebuilt for different target architectures but nothing stops you from "cross-compiling" against the host architecture. The glibc version in these docker images should be conservative enough. If it isn't, you can always configure cross to use a custom image.
In general, you need to build binaries for a given OS on that OS, or at the very least build on the oldest OS you intend to support.
glibc uses symbol versioning to preserve the behavior of older programs while adding support for new functionality. For example, a newer version of pthread_mutex_lock may support lock elision, while the old one would not. You're seeing this error because when you link against libc, you link against the default version of the symbol if a version isn't explicitly specified, and in at least one case, the version you linked against is from glibc 2.18. Changing this would require recompiling libstd (and the libc crate, if you're using it) with custom changes to pick the old versioned symbols, which is a lot of work for little gain.
If your only dependency is glibc, then it might be sufficient to just compile on CentOS 7. However, if you depend on other libraries, like OpenSSL, then those just aren't compatible across OS versions because their SONAMEs differ, and there's no way around that. So that's why generally you want to build different binaries per OS.

Can GHC link binaries against a libc implementation such as uclibc (used in OpenWrt by default)?

I am using Debian/MIPS+QEMU to build MIPS ports of PortFusion (a TCP tunneling solution). The resulting binaries are linked against GNU libc. Thus, they cannot be just copied over and used on vanilla OpenWrt which ships with uclibc instead of eglibc (which seems binary-compatible with GNU libc).
Is there a way to link Haskell/GHC binaries on Debian/MIPS against uclibc instead of eglibc?
Can OpenWrt's using uclibc be really the reason why PortFusion binaries copied over from Debian fail to run with -ash: binary not found or can this message be due to something entirely else?
See https://github.com/corsis/PortFusion/wiki/MIPS-Builds for details on which haskell-platform, Linux kernel and CPU emulation are used.
The current head of OpenWrt's GIT repository is failing at make when I attempt building custom OpenWrt images that use eglibc instead.
Is there a way to link Haskell/GHC binaries on Debian/MIPS against
uclibc instead of eglibc?
No. You need to to rebuild Haskell/GHC from sources using uclibc-based GCC cross-compiler.
Can OpenWrt's using uclibc be really the reason
Yes. Also, you can try to use ldd on your MIPS pplatform to check what library is missing. I'm sure it will be some of libc-related libraries.

using older version of a shared linux library while compiling C

I am trying to use libfann version 2.0.1 instead of the newest version 2.2.0, but could not figure out how to do so. Any thoughts on how to do that?
normally that works perfectly:
gcc fann_calculator.c -o run_fann_calculator -lfann -lm
where fann_calculator.c contains a program that calls a neural network.
Thanks
It depends upon where the two libraries sit. If they are installed in the same directory (e.g. both installed in /usr/lib/) you'll probably get the youngest one.
I suggest to carefully read the ld.so(8) and ldd(1) man pages. You certainly can trace what library is loaded (with e.g. the LD_DEBUG envirnonment variable). Don't forget to re-run ldconfig appropriately after library installation.
You could also play some LD_LIBRARY_PATH trick; for instance, set it to $HOME/lib:/usr/lib and install appropriate symlinks in your $HOME/lib/ to the precise library you want. For instance, you might do
ln -s /usr/lib/libfann.so.2.0.1 $HOME/lib/libfann.so.2
export LD_LIBRARY_PATH=$HOME/lib:/usr/lib:/lib
then check with ldd run_fann_calculator that you get the expected [version of the] libfann library.
Don't forget to read the Program Library Howto. You might want to pass appropriate flags to ld such as -rpath. You may need to pass them using gcc, perhaps with Gcc Link Options such as -Wl

compiling glibc from source with debug symbols

I need to compile glibc from source with debug symbols .
Where do i specify the '-g' option for this
How do i later make a sample code link to this particular glibc rather than the one installed on my system?
I need to compile glibc from source with debug symbols
You will have hard time compiling glibc without debug symbols. A default ./configure && make will have -g on compile line.
How do i later make a sample code link to this particular glibc rather than the one installed on my system?
This is somewhat tricky, and answered here.
It is probably a matter of configure tricks. First, try configure --help and then, either configure --enable-debug or perhaps configure CC='gcc -g' or even configure CFLAGS='-g'
For your sample code, perhaps consider playing LD_LIBRARY_PATH or LD_PRELOAD tricks (assuming linking to dynamic library).
But be very careful, since the Glibc is the cornerstone of Gnu/Linux like systems.

Installing gcc on linux without c compiler

How can I install gcc on a system that have not any c compiler?
this system is a linux base firewall and have not any c compiler.
I guess you a have an appliance running Linux and shell-access, but neither a package manager nor a compiler is installed.
So, you need to cross-compile gcc and the whole toolchain (at least binutils) - this is quite simple, because the ./configure scripts of gcc, binutils, gdb etc. support cross-compiling with the --target= option. So all you have to do is to find out the target architecure (uname helps) and then download, unpack the gcc sources on a linux-host and run ./configure --target=$YOUR_TARGET.
With this, you now can build a cross-compiler gcc - this still runs on your host, but produces binaries for your target (firewall appliances).
This may already be sufficient for you, a typical desktop PC is much faster than a typical appliance, so it may make sense to compile everything you need on the Desktop PC with the cross-compiler and cross-binutils.
But if you really wish to do so, you can now also use your cross-compiler to compile a gcc running on your target (set this as --host= option) and compiling for your target (set this as --target option).
You can find details about allowed host/targets and examples in the gcc documentation: http://gcc.gnu.org/install/specific.html.
It depends on the distribution, if it's based on debian or some other of the big ones you can install gcc through apt-get or similar tool.
If it's a more basic system you need to compile gcc yourself on another computer and copy it over. It will be easiest if you have another computer with the same architecture (i386, arm or x86_64 for example).
I think that you might want to compile it statically also, so that you don't have dependencies on external libraries.
How do you plan to get all the source code needed for GCC loaded onto your machine? Could you mount the ISO image onto this machine and install from there?
Since you are using Endian Firewall, see "Building a development box" at the following link:
http://alumnus.caltech.edu/~igormt/endian/tips.html
If it's a debian based distribution, you can use
sudo apt-get install gcc
Note: maybe you must change "gcc" by a specific version of the debian package.

Resources