Glibc and uClibc side by side on one system - c

Is it possible to have glibc and uClibc based applications running side-by-side on one system?
Background: We have binary gcc based cross-compiler configured to link with uClibc. We have cross-compiled glibc with it. Now we want to build some applications so they will link with the glibc rather than uClibc. We don't want to rebuild the compiler.

There's no problem with glibc and uClibc living side-by-side with some programs linking to one and other programs linking to the other. However, there is a problem with additional libraries. Each shared library on your system will be built against either glibc or uClibc (using the corresponding headers, which define distinct ABIs for the standard library functions), so for example if both a glibc program and a uClibc program need ncurses, you'll need to have two versions of ncurses built, and have a way of ensuring that the correct one for the given program gets loaded at runtime. Alternatively, you could choose to only use one set of shared libraries, and use static libraries for programs linked to the other libc, but you'd still need to build your 2 sets of libraries.

Yes, it should be perfectly possible, but you might have to play around with LD_PRELOAD_PATH. If you are linking statically, change to dynamic linking.

It is nearly impossible to mix them in the same FHS, as the ABI and include dir are incompatible. However, you could install either of them in an directory offset, by tweaking dynamic-linker field in ELF and exploiting sysroot feature in gcc/binutils. An on going experiment is in Gentoo community[1], known as Prefix/libc.
http://wiki.gentoo.org/wiki/Prefix/libc

Related

Are C standard library structures compatible between compilers and library versions on macOS or Linux?

My host application took over the ownership of e.g. a FILE object which came from a dynamic library. Can I call fclose() on this object safely even though my host application and the dynamic library are compiled with different versions of clang / gcc?
Background
On Windows (with different VS runtimes) it would be illegal and I have to first extract the fclose() function from the runtime library which is used by the dynamic library since all runtimes have their own pools and internal structures for file or memory objects.
An illustration for the situation in Windows would look like this:
Does this restriction apply for Linux and macOS as well?
The issue is not whether your application and the dynamic libraries were compiled with different versions of clang and/or gcc. The issue is whether, ultimately, there's one underlying C library that manipulates one kind of FILE * object and has one, compatible implementation of fclose().
Under MacOS and Linux, at least, the answer to all these questions is likely to be "yes". In my experience it's hard to get two different, incompatible C libraries into the mix; you'd have to really work at it.
Addendum: I suppose I should admit, however, that my experience may be getting dated. In my experience, on any Unix-like system, there's exactly one C library, generally /lib/libc.{a,so}. But I gather that "modern" compilers are tending to access their own compiler- and version-specific libraries off in special places, meaning that the scenario you're worried about could be a problem. To me, it seems, this way lies madness, but then again, it seems that more and more of the world seems to be embracing dependency hell, rather than trying to eliminate it.
It is not generally safe to use a library designed for one compiler with code compiled by a different compiler. A compiler may generate code that implements the nominal functions in the standard library using internal routines or interfaces, and those routines or interfaces may be different or missing in the library designed for another compiler.
Nor is it safe to take any pointer to some internal data structure from one library and use it with another library.
If the sources are just compiled with different versions of one compiler (e.g., clang 73 and clang 89), not different compilers (e.g., Apple clang versus GCC), the compiler might offer some guarantee about library compatibility. You would have to check its documentation. Or, if the compiler is intended to use the library provided with the operating system, that could work. Again, you would have to check its documentation.
On Linux, if both your code and the other library dynamically link to the same library (such as libc.so.6), both will get the same version and implementation of that library at runtime. You can check which libraries a given dynamic library links to with ldd.
If you were linking to a library that statically linked in a supporting library, you would need to be careful to pass any structures to or from it against the same version of the library. But this is more likely to come up in practice with libc++ and libstdc++ than with libc.
So, don't statically link your library to another and then pass a data structure that requires client code to separately link to the same library.

Can I use one Linux .so for all Linux compilers?

We need to integrate a closed-source C library into our project. The other party can compile the library in any mode we need, but we support a lot of different Windows and Linux compilers.
I know a DLL will be compatible with all major Windows compilers, so we could only use one library for Windows. But I’m not familiar with Linux dynamic libraries (.so). Are these compatible across all Linux environments in a similar way?
Thanks
You may have some issues w.r.t. the version of the GNU libc against which that shared library libotherparty.so has been linked (and compiled).
You certainly need to know the version of the libc, and you might require that party to ship several variants of the binary library.
I would strongly suggest to read Drepper's paper: How To Write Shared Libraries. See also this question and Levine's linker & loader book.
If it is C code, the compiler does not matter much. What matters more is the ABI. Learn also about symbol versioning.
Be prepared to have some trouble.
You'll learn by experience that free software is preferable.
Library versions should be specified for shared objects if the function interfaces are expected to change (C++ public/protected class definitions), more or fewer functions are included in the library, the function prototype changes (return data type (int, const int, ...) or argument list changes) or data type changes (object definitions: class data members, inheritance, virtual functions, ...).
The library version can be specified when the shared object library is created. If the library is expected to be updated, then a library version should be specified. This is especially important for shared object libraries which are dynamically linked. This also avoids the Microsoft "DLL hell" problem of conflicting libraries where a system upgrade which changes a standard library breaks an older application expecting an older version of the the shared object function.
Versioning occurs with the GNU C/C++ libraries as well. This often make binaries compiled with one version of the GNU tools incompatible with binaries compiled with other versions unless those versions also reside on the system. Multiple versions of the same library can reside on the same system due to versioning. The version of the library is included in the symbol name so the linker knows which version to link with.
One can look at the symbol version used: nm csub1.o
00000000 T ctest1
No version is specified in object code by default.
Look ld and object file layout
There is one GNU C/C++ compiler flag that explicitly deals with symbol versioning. Specify the version script to use at compile time with the flag: --version-script=your-version-script-file
Note: This is only useful when creating shared libraries. It is assumed that the programmer knows which libraries to link with when static linking. Runtime linking allows opportunity for library incompatibility.
Also look here regarding ABI compatibility

Copying over glibc library

I downloaded the glibc source code, modified some portion of the standard library and then used LD_PRELOAD to use that modified standard library (in the form of an .so file) with my program. However, when I copied that .so file to another computer and tried to run the same program using LD_PRELOAD there, I got a segmentation fault.
Notice that both computers have x86-64 processors. Moreover, both computers have gcc 4.4 installed. Although the computer in which it is not running has also gcc 4.1.2 installed besides gcc 4.4. However, one is running Ubuntu 10.04 (where I compiled), while the other is running CentOS 5. Is that the cause of the segmentation fault? How can I solve this problem? Notice that I don't have administrative rights on the computer with CentOS 5.
When you LD_PRELOAD the C library, I believe you're loading it in addition to the default C library. When they're the exact same version, all the symbols match, and yours takes precedence. So it works. When they're different versions, you may well have a mix, on a per-symbol basis.
Also, the NSS (name service switch, e.g., all the stuff from /etc/nsswitch.conf) API is not stable. These modules are separate from the main libc.so, but are dynamically loaded when a program e.g., does a user id to username mapping. Loading the wrong version (because you copied libc.so over) will do all kinds of badness.
Further, Ubuntu may be using eglibc and CentOS glibc. So you could be looking at a different fork of glibc.
If your LD_PRELOAD library included only the symbols you actually need to override, and overrode them to the minimum amount possible (e.g., if possible, call the overridden function), then your library has a much higher chance of being portable.
For an example of how to do this, see (for example) fakeroot.
If you're changing so much of libc that your only choice is to override all of it, then (a) you're doing something very weird; (b) you probably want to use LD_LIBRARY_PATH, not LD_PRELOAD; see the ld.so(8) manpage for details.
It is likely that your libc is not portable between kernel versions.

automatically linking socket shared library in *nix

I am learning network programming through the sample source codes from this link http://cs.baylor.edu/~donahoo/practical/CSockets/textcode.html. During the compilation, just wondering why in Solaris environment, i have to manually link socket and nsl library in the make file but when in the linux machine, i dont need to do that ?
Documentation used: http://developers.sun.com/solaris/articles/solaris_linux_app.html
This is because linux's libc, the glibc (-lc, which is linked by default to all programs) includes socket part of POSIX; and nis/nis+ dynamic libraries in linux are loaded dynamically by libc too.
But in Solaris, there are a lot of libraries with basic functionality, which are not in libc.
(libc, libucb, libmalloc, libsocket, libxnet, etc). I think, it was a design solution to allow user link only parts of API he needs.
In linux there are some basic libraries outside libc too: libaio, librt, libm.
With separate library it is easier to update only some parts of system; and it is possible to have several implementations (e.g. to provide greater compatibility/workarounds with older versions of UNIX) of some libraries coexisting in same system.
This question is discussed a lot, e.g. http://web.archiveorange.com/archive/v/KcxCHdLNpD6NANxmAt3b http://mail.opensolaris.org/pipermail/opensolaris-code/2007-January/010316.html
are seriously considering folding libnsl and libsocket into libc.
It would be nice to move ONLY the current POSIX-based and other
standards-based functionality (Unix98 etc.) libnsl+libsocket functions
to libc and keep all the compatibilty-wrapper stuff in libnsl/libsocket
to avoid that libc gets bloated with 20years of Unix
backwards-compatibility workarounds
Because in Linux, the entire networking API is implemented in libc.so which is linked into every C program by default, while in Solaris, its implemented in separate libraries.

Relink a shared library to a different version of libc

I have a linux shared library (.so) compiled with a specific version of libc (GLIBC2.4) and I need to use it on a system with different version of libc. I do not have sources for the library in question so I cannot recompile for the new system. Is it somehow possible to change the dependencies in that library to a different libc?
If you need the .so on a system with an older glibc, you would need the source code and recompile/relink it with the older glibc. The alternative is to install the required glibc on the old system in a non-default location and adjust the LD_LIBRARY_PATH for the executable that needs this .so
If there's a newer glibc rather, it should normally not be a problem as glibc tend to be backwards compatible.
Unless your library really uses interfaces that changed (unlikely), you can just hexedit the references to versions in the resulting .so file. They're all text anyway.
Best you can do is compile the old glibc version for your system and then build your application with that glibc and your shared library. Ugly though ...

Resources