News for hackers. Stuff that matters.
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @08:51PM (#49355118)
Because glibc and GNU set a terrible precedent. On GNU/Linux systems the shared binary interpreter / loader, GCC compiler, the C library and the system C/C++ ABI all depend into each other. You cannot change any of them independently. All shared libraries depend on the specific glibc version to load them into memory to be able to use that specific glibc version as their C library and make calls like dlopen.

Shared libraries have always been broken in Linux. Unfortunately many things like GPU drivers, graphics libraries and NSS need shared libraries to dynamically load certain runtimes (because you don't want to load all possible GPU drivers in existence to your RAM). So an ecosystem has been developed on top of terrible ABI and architecture GNU/glibc provided.

Re:Solo – a .so loader for static Linux binaries by krupan on Wednesday August 19, 2026 @12:08AM (#49356662)
In what way are they "broken" when Linux runs fine on millions of boxes? Sure, it might be a pain for proprietary software, but if your app is open source it's not that hard to build it on whichever distro you want. If your app is popular enough the distro maintainer will build it for you
Re:Solo – a .so loader for static Linux binaries by asveikau on Tuesday August 18, 2026 @09:08PM (#49355259)
> system C/C++ ABI

C++ abi should not be included in this. It is independent from the other pieces and historically a source of incompatibility on its own.

Saying "C/C++ abi" as if they are the same is looney tunes, the former is very simple and stable and the latter is very complex.

Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:10PM (#49355281)
See: https://news.ycombinator.com/item?id=49355262

How libstdc++ initializes global variables absolutely depends on glibc and ld-linux.so. That is part of C++ ABI.

Re:Solo – a .so loader for static Linux binaries by account42 on Wednesday August 19, 2026 @03:52AM (#49358370)
That's libstdc++ depending on a C ABI (or a GNU ABI to be precise) but that doesn't make it a C++ ABI. You can also have global constructors in C with GCC.
Re:Solo – a .so loader for static Linux binaries by josefx on Wednesday August 19, 2026 @02:54AM (#49357865)
> the former is very simple

Somehow most of my portability issues seem to be caused by glibc, its symbol versioning and close ties to the dynamic loader. Minor versions aren't compatible, no two Linux distros ship the same version and you can't just provide your own without also patching in your own dynamic loader.

At least as far as the defaults on Linux go I consider C the root of all evil.

Re:Solo – a .so loader for static Linux binaries by badsectoracula on Wednesday August 19, 2026 @03:14AM (#49358023)
AFAIK glibc is backwards compatible as long as a) your program is running on a newer version (i.e. you're not trying to dynamically link against an older version) and b) you're not using hidden/undocumented symbols.

In which case as long as you're using the documented public API and compile your program with the oldest version of glibc you want to support (some Ubuntu from 4-5 years ago should cover pretty much every current desktop) you should be fine. And with something like Docker this is trivial to do.

Sure it is annoying that you cannot use your current distro (especially if you use some rolling distro) to make binaries for everyone, but it takes very little effort to work around that. The only issue i can think of is if you absolutely want to compile using the latest version of your compiler and you cannot build the compiler from source to work in the Docker (or whatever) contain to work against the older glibc.

Re:Solo – a .so loader for static Linux binaries by pg83 on Wednesday August 19, 2026 @04:11AM (#49358538)
This approach only works for very simple cases.

In complex cases, it turns out that the old version of glibc also pulls in other libraries and the compiler, and you're stuck with a very ancient sysroot. You may often find that you can't compile new library versions in such a sysroot and link them statically.

So, it looks good on paper, but forget about the ravines.

Re:Solo – a .so loader for static Linux binaries by asveikau on Wednesday August 19, 2026 @08:54PM (#49369162)
Still very simple compared to c++.
Re:Solo – a .so loader for static Linux binaries by adev_ on Tuesday August 18, 2026 @10:57PM (#49356088)
> All shared libraries depend on the specific glibc version to load them into memory to be able to use that specific glibc version as their C library

That's currently the real core of the problem.

The loader (and libdl) need to be decoupled from the glibc itself under Linux.

Without that, any attempt to ship static binaries (or any binary with a different Libc) will be a source of perpetual pain.

nss plugins and its associated pain (sssd and avahi) are an other examples of that.

Re:Solo – a .so loader for static Linux binaries by inigyou on Wednesday August 19, 2026 @08:38AM (#49360764)
libdl is the loader FWIW. It's all one big glibc codebase.
Re:Solo – a .so loader for static Linux binaries by adev_ on Wednesday August 19, 2026 @08:52AM (#49360916)
What we name the loader is typically ld.so, more precisely /lib/ld-linux-x86-64.so.2 under x86_64.

But I do agree with you, the glibc is all one giant codebase shipped in one giant blob, dispatch under several names.

Even libdl.so is barely more than a wrapper and some glue around the libc.so itself.

Re:Solo – a .so loader for static Linux binaries by uecker on Tuesday August 18, 2026 @09:00PM (#49355197)
In what sense do binary interpreter / loader, GCC compiler, C library and system C/C++ ABI dependent on each other? I have certainly mixed different versions of all these components without problems so far.
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:09PM (#49355262)
When you compile GCC you need to provide a full glibc installation as your target. It is also a dependency of libstdc++.

C++ global/static variable initialization depends on the specific version of glibc (they don't usually break compat, but they can and they did in the past) which also provides ld-linux.so that loads those global variable placeholders in the correct manner such that glibc and libstdc++ can initialize them correctly.

This is just one example. Thread local variables and behavior of things like pthreads with signal, fork etc all depend on glibc.

Re:Solo – a .so loader for static Linux binaries by uecker on Tuesday August 18, 2026 @09:20PM (#49355342)
I can't comment on the C++, I can imagine there plenty of issues, but for C I don't see this. You need some libc if you compile with gcc, but this generally does not introduce a hard version dependency on the specific version (there may be a minimum requirement if you compile against a new version that a symbol with a different ABI).
Re:Solo – a .so loader for static Linux binaries by pg83 on Tuesday August 18, 2026 @09:14PM (#49355301)
For example, the itanium unwind ABI implementation lies between these three entities.
Re:Solo – a .so loader for static Linux binaries by mananaysiempre on Tuesday August 18, 2026 @09:19PM (#49355340)
I don’t imagine that you’re unaware of any of this, but: ld.so and libc.so are heavily interdependent in deliberately undocumented ways with Glibc and outright the same file with shared Musl. And while you might usually get away with using any old GCC with the right architecture and ABI (especially for C; cf the musl-gcc hack), technically it needs to be built to target a specific libc version (particularly via symbol versioning; I’ve long wanted to gather a set of patches to build an old Glibc and subsequently a cross-compiler using a new GCC so I could avoid PyPA’s manylinux monster or its moral equivalent for compatible dynamic binaries in simple cases). The C compiler of course is tied to the C ABI, and this wouldn’t be really worth mentioning except for the time where the GCC devs accidentally the whole SysV i386 ABI and pretended that the stack was always 16-byte aligned, why do you ask, except on RHEL. The C++ parts I can’t really comment on.
Re:Solo – a .so loader for static Linux binaries by uecker on Tuesday August 18, 2026 @09:27PM (#49355401)
I am not really sure. For ld.so and libc.so I may believe this. The C ABI is very stable, and if you use a new symbol from a newer glibc, you certainly depend on it, but this can also be avoided. In any case, I do not see what is fundamentally misdesigned here. I can't quite image how it could work differently. If you upgrade something so that the e ABI changed you natually need to update other components. Static linking certainly seems a very poor replacement for this.
Re:Solo – a .so loader for static Linux binaries by account42 on Wednesday August 19, 2026 @03:56AM (#49358410)
> I’ve long wanted to gather a set of patches to build an old Glibc and subsequently a cross-compiler using a new GCC so I could avoid PyPA’s manylinux monster or its moral equivalent for compatible dynamic binaries in simple cases

And that's the correct approach and also one that many have taken. We just need someone willing to maintain that as an easy mode SDK for everyone.

Re:Solo – a .so loader for static Linux binaries by pg83 on Wednesday August 19, 2026 @04:20AM (#49358606)
> And that's the correct approach.

Who said that? This approach has many problems that have already been discussed here, not to mention the fact that it leaves Alpine and Bionic-based systems out in the cold.

Let me remind you that Bionic is the most widespread libc in the Linux world, and Alpine is the most popular Docker layer.

The world doesn't end with glibc. And it doesn't begin with it.

Re:Solo – a .so loader for static Linux binaries by uecker on Wednesday August 19, 2026 @06:22AM (#49359488)
It could be fine if you care only about free-software desktop users, and not Google's propriety platform and hyperscalers.
Re:Solo – a .so loader for static Linux binaries by duped on Tuesday August 18, 2026 @09:14PM (#49355304)
The interpreter/loader is glibc and a key part of bootstrapping an executable built against glibc is loading libc itself before continuing on to load the program. Versioning is a problem when distributing binaries linked against a newer glibc to distros that ship an older one. The C compiler doesn't really care as much.
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:32PM (#49355424)
> The C compiler doesn't really care as much.

Until you define a thread local variable (C11) or use atomics (also C11) or define a global with an initial value. Then it happily generates code that depends on "whatever my target glibc + ld-linux.so needs".

Re:Solo – a .so loader for static Linux binaries by uecker on Tuesday August 18, 2026 @09:48PM (#49355535)
It depends on functions defined in a standardized ABI.
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:51PM (#49355555)
You'd expect that but, no. That's why you cannot load glibc-linked binaries in a Musl distro. Edit: that's why the hacks like the original post is needed, as well.

The ABI is strongly dependent on explicit libc implementation in current Linux systems. There is no libc independent ABI on Linux.

Re:Solo – a .so loader for static Linux binaries by uecker on Tuesday August 18, 2026 @09:54PM (#49355575)
Sorry, can you be more specific. I do not understand what the problem is. If Musl does not implement support for the ABI, this would be a musl problem?
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @10:03PM (#49355646)
There is no libc independent ABI. ABI doesn't purely mean just calling conventions.

When you compile libc, you also get a binary loader ld-linux.so with it. They are not two independent components of a system.

Basically all .so files compiled with glibc require the ld-linux.so that's also generated by that glibc (or a later version, if they didn't break the binary compatibility).

There are a lot of stuff that's executed by ld-linux.so and glibc that are not explicitly documented but they are absolutely necessary for your program to start and correctly initialize things like global variables or signal handling or loading other dynamic libraries. Some of that functionality sits in ld-linux.so and some of that in glibc. They have circular dependencies to each other. glibc expects ld-linux.so to put things in certain order but ld-linux.so also must load glibc first to have access to certain APIs. They are not part of System V ABI. They are not documented.

Musl maybe can implement this but it is simply reverse engineering what glibc did and then playing a game of cat and mouse. There is no independent ABI standard.

Re:Solo – a .so loader for static Linux binaries by uecker on Wednesday August 19, 2026 @06:06AM (#49359362)
Sorry, again this too vague for me. What is the exact problem with atomics and thread_local in C that would make the ABI dependent on a specific version of glibc? I know the ABI is not just calling convention and e.g. for atomics may involve calling a function from libatomic. But from my understanding, this is all part of a standardized ABI that does not change and can be provided by different implementations.

Then, what is the exact reason a library compiled against glibc must be loaded by a specific ld-linux? I could see that this is true for C++ perhaps, or when you use very special features, but I do not see this for C.

I often compiled programs against one version of glibc and run it against a different version, so I know there is not a tight coupling. So please be specific in explaining in what scenarios this would break.

Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @07:12PM (#49368393)
Here read it from the lion's mouth: https://wiki.musl-libc.org/design-concepts

> Then, what is the exact reason a library compiled against glibc must be loaded by a specific ld-linux? I could see that this is true for C++ perhaps, or when you use very special features, but I do not see this for C.

You still have functionality like `dlopen` with C or `pthreads` with C. ld-linux.so is the thing that prepares the stack frame, or the segment pointers (FS_BASE on x86_64).

When you have your main loaded __libc_start_main_impl is called from glibc and if you disassemble it you'll see this line:

call 0x7ffff7c28790 <_dl_audit_preinit@plt>

Guess where _dl_audit_preinit lives?

(gdb) info symbol _dl_audit_preinit _dl_audit_preinit in section .text of /lib64/ld-linux-x86-64.so.2

Moreover glibc has "magic" sections like .init_first. Only ld-linux.so that is compiled from glibc source knows how to handle that. https://elixir.bootlin.com/glibc/glibc-2.44.9000/source/csu/...

> I often compiled programs against one version of glibc and run it against a different version, so I know there is not a tight coupling. So please be specific in explaining in what scenarios this would break.

It didn't break, since glibc hasn't broken backwards compatibility of ld-linux.so and glibc combination lately. Last time they broke it was in 2024 for a really specific subset: https://sourceware.org/pipermail/libc-alpha/2024-December/16...

A breakage hasn't been observed doesn't mean that there is no tight-coupling between ld-linux.so and glibc that is compiled from glibc source.

If you want a really specific scenario:

- Write a very simple C file that contains a global (volatile if you want to stop the compiler optimizations) thread_local variable with C23 syntax

- Compile a simple .so file on a GNU distro targetting glibc ABI with GCC (pass -std=c23)

- start up a Musl distro (e.g. Alpine Docker image), copy that .so file in

- Write a C program that dlopens the GNU .so file

- Try accessing the thread_local variable you defined

- Watch the world burn

Re:Solo – a .so loader for static Linux binaries by uecker on Wednesday August 19, 2026 @07:50PM (#49368723)
Thanks, I need to dig into this more. But I still not convinced there is a real issue here. Of course different infrastructure needs to exist for different feature. What exactly is the underlying issue with thread_local in your specific scenario? It seems Musl does not setup the the infrastructure needed for ABI-compliant thread-locaL data access?
Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @08:59PM (#49369190)
THERE IS NO STANDARD, AGREED ON, RFC'd or EVEN BEHAVIORALLY DOCUMENTED ABI FOR MUSL TO FOLLOW!

It's not Musl's fault that Glibc has an undocumented, badly designed, tightly coupled implementation. It's not Musl's fault when they decide to not follow Glibc's design which they have to reverse engineer and rewrite from scratch. Then Glibc can break it in a future version anyway. They give 0 guarantees and have a track record of breaking things.

Sorry but I feel like you're trying to excuse Glibc out of their terrible design. Glibc didn't ask anybody for standardization. Glibc didn't document their behavior. Musl doesn't need to follow any undocumented behavior. Musl has its own implementation of thread_local variable and it works only for Musl dynamic binaries (which you cannot load with Glibc's ld-linux.so either). You need to tell your compiler to generate code that Musl prefers not Glibc. So effectively we have two ABIs.

There is no standard and any design that tightly couples the system binary loader to the C standard library is just extremely terrible design. Both Musl and Glibc do it. Both of them are terrible. Glibc was first and it set the horrible, binary hostile behavior "have no standards, trust Glibc, and recompile your programs again" as the "standard".

The entire Linux userspace depends on Glibc's terrible design. Due to Hyrum's Law, the exact needs of the complex and emergent behavior can only be surfaced via making a better designed, completely independent system loader and a completely independent libc and then fixing the entire tens of thousands of userspace libraries in the upcoming decades. It is just Sisyphean work to fix Linux userspace.

There is no simple "let libc-X obey the standard S" solution. There is no standard. Linux Standard Base project tried to set a standard. It failed.

I'll won't further discuss this with you. Maybe you have good intentions, maybe you're playing dumb. I'm not sure anymore. If you're the former, I'm not going to deliver every single bit of information. I provided enough resources and you can learn.

Re:Solo – a .so loader for static Linux binaries by nomel on Wednesday August 19, 2026 @10:06PM (#49369624)
As a naive third party, wondering the same things he was at each point in the conversation, I think you definitely read him wrong.

But, thanks for spending the time! I learned a bunch!

Re:Solo – a .so loader for static Linux binaries by uecker on Wednesday August 19, 2026 @09:01PM (#49369211)
sorry you are just ranting. I was asking for specific details. The documentation for TLS seems this: https://www.uclibc.org/docs/tls.pdf
Re:Solo – a .so loader for static Linux binaries by duped on Wednesday August 19, 2026 @10:29AM (#49362124)
Unless you use musl-gcc which is a proper GCC frontend with musl libc sysroot. The compiler is indeed (too) tightly coupled to its sysroot but linux is not special here. If anything interacts with the CRT it needs to know which CRT to use.

I'm not arguing that there aren't problems here, just that I think people have different expectations that are a little extreme. The libc implementation is a core part of the operating system, if you want to target that OS you should target that libc. Some distros (alpine) prefer musl libc, most prefer glibc. And distros really are different operating systems.

Re:Solo – a .so loader for static Linux binaries by b5n on Tuesday August 18, 2026 @09:11PM (#49355283)
While I don't disagree with some of the pain you describe, you conveniently gloss over the fact that gnu developed a system that worked, and then made it free to everyone to consult and use.
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:12PM (#49355292)
BSD also did it. They did it better. Maybe more modern but AOSP also did it but at a different level of binary: instead of ELF, using compiled Java bytecode archives.
Re:Solo – a .so loader for static Linux binaries by lmz on Wednesday August 19, 2026 @01:11AM (#49357113)
The root cause is alternative libc implementations. Are BSD syscalls considered stable? I remember Go moving to use libc on OpenBSD. Solaris also has the libc as the stable interface. Linux kernel is an outlier here guaranteeing stable syscalls but you wanting to use another libc is not Glibc's problem.
Re:Solo – a .so loader for static Linux binaries by account42 on Wednesday August 19, 2026 @03:54AM (#49358391)
Yeah it's not Linux specific but rather true for most Unix systems that libc == base system interface library.
Re:Solo – a .so loader for static Linux binaries by pjmlp on Wednesday August 19, 2026 @04:23AM (#49358631)
Except the other UNIX systems, starting with the original one, evolved from only having static linking to various ways to connect libraries and applications.
Re:Solo – a .so loader for static Linux binaries by duped on Tuesday August 18, 2026 @09:12PM (#49355291)
> all shared libraries depend on the specific glibc version to load them

Not really, though. glibc uses symbol versions that are forward but not backward compatible. If you got an error that said "this program was built for a newer version of <distro>" would you say the same thing?

Note this is the same (if not worse) on MacOS, and on windows you used to distribute the CRT with your application just to deal with the same problem.

Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:21PM (#49355351)
See https://news.ycombinator.com/item?id=49355262 .

Yes glibc has some backwards compat but you cannot load a binary compiled with a newer version of glibc using an older ld-linux.so. That's because the interdependency. Nor you can load binaries that depend on different libc.so files with glibc systems

I cannot comment on macOS, I have never used it. However this is not a problem with Windows. You can ship a newer CRT or you can install it as a system component using Microsoft's MSI. The dependency is one way on Windows. CRT purely depends on Win32. Moreover the loader is completely independent and DLLs are loaded into their own unique scoped namespace unlike Linux that loads them in global symbol namespace. That's why you can mix and match DLLs compiled for different CRT versions.

Re:Solo – a .so loader for static Linux binaries by duped on Tuesday August 18, 2026 @09:27PM (#49355394)
That's what I'm saying though, glibc-linked binaries are forwards (but not backwards) compatible.
Re:Solo – a .so loader for static Linux binaries by okanat on Tuesday August 18, 2026 @09:37PM (#49355458)
It is not just compatibility. You cannot load them into the memory with your system dynamic loader. You need to also ship ld-linux.so with the new version of glibc you have, if you were to distribute your program independently.

On Windows you don't need to ship a new binary loader. I can just ship Windows 10 UCRT DLL (which is the new libc of Windows) to Vista and my binaries will work. The binary loader isn't interlinked with the libc.

Re:Solo – a .so loader for static Linux binaries by cylemons on Wednesday August 19, 2026 @01:44AM (#49357346)
Windows doesn't even have a concept of a loader binary right? I think its hardcoded into the kernel/win32 itself.
Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @03:35AM (#49358215)
Windows loader is part of the system ABI, and programs' libc(s) are loaded by it.

One of the ways Windows manages to support multiple libc's is by being careful not to mix allocators; if a system API you call allocates on your behalf, your libc can't free it, the system API will offer a function to free it.

Windows loader is certainly available to user programs though; LoadLibrary has been around longer than many developers.

Re:Solo – a .so loader for static Linux binaries by account42 on Wednesday August 19, 2026 @04:01AM (#49358465)
LoadLibrary will also not be able to load arbitrary libraries compiled for newer versions of Windows though. Just like with gcc, Windows also does not guarantee forwards compatibility - because that would men freezing the feature set the system libraries provide.
Re:Solo – a .so loader for static Linux binaries by pg83 on Wednesday August 19, 2026 @04:23AM (#49358633)
Windows handles this much better than any other OS. The API passes versions (== structure sizes on the calling side), and WinAPI can handle that.

As for older Windows systems not being able to load new DLLs, they can; the format hasn't changed in a very long time. I've had experience with installing some DLLs on Windows NT 3.51 and running a modern Firefox, which is about 20 years behind the times.

Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @05:02AM (#49358921)
Targeting an older version of Windows is "set a define so that the system headers don't expose functions that didn't exist on older Windows". You don't need an old toolchain to target old systems, you ask the newer toolchains to target it.

MS haven't made this work arbitrarily far back, I believe they deprecated targeting Windows XP in one of the more recent toolchains, but that was purely a "not worth supporting" situation.

EDIT: mixed up talking about older & newer

Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @07:41PM (#49368655)
It kind of does but in a "it is an implementation detail that you cannot access and it doesn't matter" sense. Unlike ELF, PE32+ files do not have an "interpreter" that you can specify.

csrss.exe handles some of the loading functionality: https://en.wikipedia.org/wiki/Client/Server_Runtime_Subsyste...

Re:Solo – a .so loader for static Linux binaries by duped on Wednesday August 19, 2026 @10:17AM (#49361957)
Why? If you compile your program against an older glibc it will run on newer glibc. glibc is the loader.
Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @08:03PM (#49368817)
Why? What kind of single-responsibility-principle that predicates the C standard library to become the both syscall interface and the binary loader as well?

What happened to the Unix principle "do one thing and do it well"? Windows solved this quite modularly and it works perfectly well.

Glibc is terribly designed and it is the core component of almost any Linux userspace app today. Let's not try to find excuses for horrible designs.

Re:Solo – a .so loader for static Linux binaries by duped on Wednesday August 19, 2026 @10:54PM (#49369863)
I don't disagree that the loader and the libc should be decoupled, but it's not as simple a split as you're making it out to be.

The reason they're tightly coupled is because there needs to be a bridge between Sys-V ELF ABI and the C runtime, and it makes sense for the implementation of that bridge to use libc itself which means special-casing the bootstrapping of libc during program loading.

glibc isn't unique here btw - musl libc ships its own loader that does the exact same thing as rtld (parse auxv/envp off the stack, relocate itself and load libc, initialize the CRT, then load the rest of the program's SOs in order).

Even if they were fully decoupled it is not unreasonable for software targeting newer versions of an operating system to only run on that version or later. Linux is actually the outlier here where the syscall interface is stable enough to make this a non-obvious problem.

There's a universe where you can load multiple versions of the same libc into the same address space but that isn't ELF, and it's not common. aiui the only reason PE can support e.g. multiple versions of malloc/free in the same executable is due to two level namespaces in symbol relocation tables.

---

edit: another observation is that for a functioning ELF loader you basically need a three stage bootstrap. Stage one parses the stack passed by the kernel and performs self-relocation. You need that to make non-static function calls and read/write global variables. Stage two loads libc and initializes the CRT with stuff like environment variables, aux vector, any dso for syscalls passed by the kernel, etc. That has to coupled because POSIX specifies stupid stuff like "getenv" and "argv" requires the loader to know how to move from the stack passed by the kernel to the memory reserved by the CRT that gets used by the final executable. Finally in stage 3 it can relocate and load shared objects and run any constructor functions pre-main, before jumping to start where the precompiled CRT start (then jump to main goes).

So if you want an ELF loader on Sys-V you probably need to couple the loader to the libc, just for libc to work at all. Unless you want to specify a bunch of behavior and binary layout in the C standard.

None of this is designed by glibc, it's the simplest way to go from exec to main.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @02:52AM (#49357854)
Yeah, it's mind boggling how everything hard depends on glibc, even critical graphics systems.

I've become obsessed with getting rid of it, especially after I realized that contributing to GNU itself was a dead end. Freestanding Linux programming turned out to be much more fun anyway.

All libraries out there should adopt the SQLite design: programmers provide it with all the necessary functions. Instead of libraries hard depending on glibc, we get to inject the libc-ish subset it needs. Then we can use whatever we want under the hood. I'm working on porting SQLite to freestanding Linux system calls so it can run with zero dependencies. Wish I could say the same for software like mesa, I'd need a lot of help for this one...

Re:Solo – a .so loader for static Linux binaries by yxhuvud on Wednesday August 19, 2026 @03:55AM (#49358398)
Modularizing (and versioning each part independently) libc would go a long way. There is also a need to separate the stuff needed for system integration with what is necessary for users of the C language to actually do stuff.
Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @04:09AM (#49358532)
> Modularizing

Can't be done. The libc is legacy, it can't be changed without breaking everything. It's also mandatory on every operating system other than Linux.

> what is necessary for users of the C language to actually do stuff

Surprisingly little. I wrote an entire lisp interpreter in freestanding C with Linux system calls. It managed to survive for a rather long time without any memory allocation at all.

The system layer is refreshingly tiny. It consists of a memory allocator and extremely basic functions like memmove and strlen. I successfully got rid of total nonsense like thread local errno, locales, implicit buffering, cached global state, possibly more. All that stuff is gone!

Re:Solo – a .so loader for static Linux binaries by pg83 on Wednesday August 19, 2026 @04:39AM (#49358749)
> A change in paradigm is necessary. Freestanding C, not hosted C. This completely gets rid of the libc and is a surprisingly clean language. Linux only, because it's the only kernel with a stable binary interface. Every other OS forces a C runtime.

Great choice for small programs, but what if I want hardware accelerated 3d?

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @04:50AM (#49358835)
Yeah, that's the annoying part. Been wondering about this for years, and graphics support was among the first issues raised on the lone lisp GitHub repository. At this point I've even started exploring the mesa codebase, made some patches but didn't submit them yet due to the AI stigma.

With Linux system calls alone it should be possible to set up kernel mode setting without depending on any toolkit at all. This should be enough to get a framebuffer for software rendering.

For hardware acceleration though, one must give this graphics context to an OpenGL ES implementation. That's where it gets ugly. There is no way to divorce that from the libc short of literally rewriting it.

Maybe Vulkan will enable it? I can't say for sure at my current knowledge level.

Re:Solo – a .so loader for static Linux binaries by pjmlp on Wednesday August 19, 2026 @08:03AM (#49360385)
Vulkan is designed to only load core statically and the whole extension spaghetti dynamically, using driver entry points.

https://vulkan.lunarg.com/doc/view/latest/mac/LoaderInterfac...

Re:Solo – a .so loader for static Linux binaries by Splizard on Wednesday August 19, 2026 @04:44AM (#49358780)
exactly
Re:Solo – a .so loader for static Linux binaries by inigyou on Wednesday August 19, 2026 @08:40AM (#49360777)
Modern 3D APIs are built around passing around a few buffers per frame and long command queues. Should be doable with IPC.
Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @04:54AM (#49358866)
> Can't be done. The libc is legacy, it can't be changed without breaking everything. It's also mandatory on every operating system other than Linux.

Windows explicitly does not want you to link the system libc. You are expected to bring your own, and doing so means your process has multiple libc's loaded into its address space.

And if you choose to build a binary that doesn't need a libc, you won't be bringing one.

Re:Solo – a .so loader for static Linux binaries by delta_p_delta_x on Wednesday August 19, 2026 @07:21AM (#49360012)
> Windows explicitly does not want you to link the system libc

This is categorically false; UCRT[1] is a thing. The 'U' stands for universal. Unlike Linux, Windows allows developers to choose their ABI boundary and also ship that boundary if they desire, or use the 'system' one and ask older platforms to install redistributables or Windows update packages. There's the old and new C runtimes in MSVCRT.DLL and UCRTBASE.DLL, the C++ runtime in VCRUNTIME140.DLL, Win32 in KERNEL32.DLL, USER32.DLL and more, and then the stable-ish kernel interfaces in NTDLL.DLL, in order of 'closeness to the kernel'.

And also, 'libc' is a UNIXism; on Windows the term is CRT, for 'C runtime'.

[1]: https://learn.microsoft.com/en-gb/cpp/porting/upgrade-your-c...

Re:Solo – a .so loader for static Linux binaries by pjmlp on Wednesday August 19, 2026 @08:08AM (#49360435)
That was introduced in Windows 10, Windows history is a long one.

Usually Windows developers will use Win32 directly, ZeroMemory() instead of memset(), and so on.

Re:Solo – a .so loader for static Linux binaries by delta_p_delta_x on Wednesday August 19, 2026 @08:10AM (#49360459)
Indeed. I was just about to point out the fact that the CRT only provides the C standard library; Windows applications can run perfectly fine without one by linking only to the Windows API DLLs.
Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @07:29AM (#49360087)
By "system libc" I'm only referring to msvcrt.dll, found in the Windows directory. Quoting Raymond Chen:

> At some point, the decision was made to just give up and declare it an operating system DLL, to be used only by operating system components.

https://devblogs.microsoft.com/oldnewthing/20140411-00/?p=12...

Re:Solo – a .so loader for static Linux binaries by delta_p_delta_x on Wednesday August 19, 2026 @08:05AM (#49360404)
I think the grander point is that there is no real 'system CRT' on Windows; as I mentioned, there are multiple entry points each at an appropriate level of abstraction available to both platform and application developers (not that there is a real difference between the two, since platform developers may also write applications like Office). Many Windows platform libraries (WIL, for instance) themselves use UCRT instead of MSVCRT now. The latter exists, but it is by no means and has not ever been by any means the single entry point to the Windows platform, unlike glibc on most desktop Linux distributions.
Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @07:35PM (#49368598)
You can completely skip all CRTs on Windows and still have a program that can call dynamic loader and other Win32 APIs. Here is a tutorial: https://nullprogram.com/blog/2023/02/15/

When you link with UCRT your specific program just gets a "view" of standard C functions. You can load DLLs that were linked with MSVCRT from a UCRT program. It just works

Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @08:17PM (#49368903)
That's a pretty great article. Re. the stack probes, it's not hard to supply your own; Raymond Chen recently did a blog series on stack probes, the entries for amd64 and arm64 are here:

amd64: https://devblogs.microsoft.com/oldnewthing/20260319-00/?p=11...

arm64: https://devblogs.microsoft.com/oldnewthing/20260320-00/?p=11...

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @08:29AM (#49360660)
> Unlike Linux, Windows allows developers to choose their ABI boundary

Linux has a stable system call ABI. I can trash the entire user space and boot Linux with init=/my/program if I want.

It's not that Linux doesn't allow developers to choose, it's that Linux doesn't actually control the userspace ABIs. Userspace is whatever we want it to be, and people settled on "GNU/Linux".

Re:Solo – a .so loader for static Linux binaries by delta_p_delta_x on Wednesday August 19, 2026 @08:47AM (#49360874)
> Linux has a stable system call ABI

This is a noble but practically worthless ideal. Hardly anything is written against the kernel ABI except glibc itself. End-user application developers don't write against the kernel interface. Platform library and application developers like KDE and GNOME don't really write against the kernel interface either. Nowadays even driver developers don't entirely write against the kernel interface, instead also linking in glibc and lib{std}c++ for things like shader compilers (which is nowadays usually just a fork of Clang). Like it or not, glibc is the singular entry point for desktop Linux, which is the point of essentially every comment under this post.

That 'desktop Linux ≡ glibc' is something that I daresay the kernel developers also have to take responsibility for, rather than shrugging their shoulders and pawning it off to GNU. Linux's unstable user-mode is the entire reason for Docker's existence. It is bodge upon bodge and has led to much gnashing of teeth. The GNU/Linux community (I don't care for Stallman's meme rant here) have to grow a backbone and understand that an OS is much more than just a kernel, it is a platform, and currently the Linux platform is a disparate set of communities with highly divergent goals.

That's why I've always said the best Linux is Android, because Android is a platform.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @09:28AM (#49361349)
> Hardly anything is written against the kernel ABI except glibc itself.

I'm working hard to change that.

Here's an entire lisp interpreter written in freestanding C using nothing but Linux system calls:

https://github.com/lone-lang/lone

It has a system-call primitive too, which means it can do anything.

Here's a TCP echo server written in lone lisp:

https://github.com/lone-lang/lone/blob/master/examples/tcp-e...

It works, and you don't need libc.

> Like it or not, glibc is the singular entry point for desktop Linux

Well I don't like it, and I've made it my mission to fix it.

Maybe lisp isn't the answer, Rust is. I've revived my liblinux crate too.

https://github.com/matheusmoreira/liblinux

I'm going to add system calls to this thing every day until I have every single one. Then I'll use them to make all of my applications.

Already have my first project planned: a custom Rust network stack for my QEMU virtual machines so I can firewall them off in userspace without root access.

> the Linux platform

The linux platform is these system calls. Everything else is userspace. This is exactly what makes it special.

https://www.matheusmoreira.com/articles/linux-system-calls

Re:Solo – a .so loader for static Linux binaries by delta_p_delta_x on Wednesday August 19, 2026 @10:12AM (#49361905)
> The linux platform is these system calls. Everything else is userspace. This is exactly what makes it special.

This is exactly the attitude I meant by 'the kernel developers also have to take responsibility for, rather than shrugging their shoulders and pawning it off to GNU' and 'an OS is much more than just a kernel, it is a platform'.

By 'platform', I mean windowing toolkits, such as Wayland. Audio libraries like ALSA and PipeWire. Desktop idioms and libraries like DBus, and the entire freedesktop.org effort including Mesa and more. Init systems like systemd. Bootloaders like GRUB/systemd-boot. Networking, including systemd-networkd, iwd, and NetworkManager. Power and device management including PowerDevil, Bluez.

If all of this is considered 'user space' then my point is strongly vindicated. On most competitor OSs these comprise the 'platform'. You won't ever encounter a Windows or OS X developer arguing that USER32.DLL or Foundation is 'userspace' even if it is technically true and code from those libraries may only ever run in ring 3. From the average user's point of view, the only 'userspace' are end-user applications that they have installed, like Chrome, video games, etc. From that perspective, even purely user-mode applications that ship with the distro ought to considered 'platform'. This includes such trivia like calculator and camera applications.

We need to talk about the practical realities of a platform, not a theoretical, unattainable, and as I mentioned, useless ideal. These practical realities mean shipping a unified set of useful 'batteries included' user-mode libraries and applications. If one wants to develop the platform itself, then sure, the kernel has a nice stable interface, but on most Linux distributions the kernel is built from source anyway, so even that nicety is moot.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @10:41AM (#49362309)
> By 'platform', I mean

You mean Linux distributions.

> From that perspective, even purely user-mode applications that ship with the distro ought to considered 'platform'.

Every Linux distribution is its own platform.

You decried Stallman's meme rant yet you just rewrote the entire rant in your own terms. Linux is the kernel, GNU's just the stuff on top. You can get rid of it if you want and make your own. Android did exactly that.

Re:Solo – a .so loader for static Linux binaries by yjftsjthsd-h on Wednesday August 19, 2026 @09:58AM (#49361717)
It's more than a little funny that you disparage syscalls being Linux's stable interface, and then immediately praise Android, which only works because glibc isn't uniquely privileged the way you seem to want.

Also, I daily drive Alpine Linux (using musl) and I'm quite happy to assure you that glibc really is only one option, not at all mandatory for desktop Linux.

Re:Solo – a .so loader for static Linux binaries by delta_p_delta_x on Wednesday August 19, 2026 @10:18AM (#49361976)
> It's more than a little funny that you disparage syscalls being Linux's stable interface, and then immediately praise Android, which only works because glibc isn't uniquely privileged the way you seem to want.

I never disparaged it; I said having it doesn't make it any more useful that OSs that don't, because the practical reality is that the kernel interface is narrow and highly technical, and a stable kernel binary interface has little to do with a user's day-to-day experience with an OS.

I daresay Android would still work pretty well even sans the kernel ABI stability, because the kernel is usually built from source, and if it isn't, then every Android source tree has kernel prebuilts for the kernel version shipping. I also never said nor implied glibc should be uniquely privileged; I think you have misrepresented my comment.

Re:Solo – a .so loader for static Linux binaries by stevefan1999 on Wednesday August 19, 2026 @12:04PM (#49363382)
> There's the old and new C runtimes in MSVCRT.DLL

Some advertisement for VC-LTL: https://github.com/Chuyu-Team/VC-LTL5 and https://github.com/Chuyu-Team/YY-Thunks

VC-LTL Implements a good subset of modern CRT functions using the msvcrt.dll, which makes modern MSVC compiler to emit binaries that theoretically can run in Windows NT 4.1 or Windows 98 (until CFG broke them, but you can turn it off). Still can teach an old dog new tricks.

YY-Thunk is a little more funky, it tries to implement new Win32 userspace API for old system by emulating the behavior and expected values using userspace API in the old apartment, so you can try to implement a function in Windows 10 with functions in Windows Vista, and hopefully it will work out.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @06:02AM (#49359325)
> You are expected to bring your own, and doing so means your process has multiple libc's loaded into its address space.

That only massively compounds the problem.

> And if you choose to build a binary that doesn't need a libc, you won't be bringing one.

NT system calls are not stable. You still need to link against ntdll.dll at the very least, like a forced Linux vDSO.

Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @06:11AM (#49359397)
> That only massively compounds the problem.

The Windows ecosystem, that manages to deliver built binaries easily & widely, regardless of whether the author has a 1 year old OS or a 15 year old OS, suggests that it's not as big a problem as you believe.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @06:37AM (#49359639)
It's not a problem in the same way that things like snap or flatpak aren't problems. It works but it bloats things up considerably and makes you wonder where it all went so wrong. I mean, dozens of slightly incompatible runtimes inside a single process?
Re:Solo – a .so loader for static Linux binaries by dwattttt on Wednesday August 19, 2026 @06:54AM (#49359789)
Those incompatible runtimes are separated by a linker that doesn't resolve all symbols globally, but rather scoped to the shared object they're expected from. They all coexist happily, and if you're so inclined you could resolve the same symbol from each, if you had reason to do so.
Re:Solo – a .so loader for static Linux binaries by torginus on Wednesday August 19, 2026 @06:03AM (#49359338)
>A change in paradigm is necessary. Freestanding C, not hosted C. This completely gets rid of the libc and is a surprisingly clean language. Linux only, because it's the only kernel with a stable binary interface. Every other OS forces a C runtime.

I'm sure those OSes make efforts to make said runtime binary compatible between executables.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @06:34AM (#49359598)
Yes, but the whole idea is to delete the runtime binary and talk to the kernel directly.

That's when you run into the Darth Vader of binary interfaces.

> I have altered the ABI. Pray I do not alter it further. -- De Raadt

Re:Solo – a .so loader for static Linux binaries by torginus on Wednesday August 19, 2026 @10:49AM (#49362419)
I am not sure having a stable kernel ABI/API is really a goal in practice or intent in all cases.

GPU drivers are a perfect example - GPUs are hellishly complex, and their interfaces are super high-level - OpenGL/Vulkan is not something that should be implemented by the driver.

I think a general practice that is followed with GPU drivers is to move as much of the complex and non-privileged stuff out of the kernel, and only keep modesetting/power management/memory and control stuff in.

That reduces massively the amount of code that needs to run in Ring 0, but in exchange, the interface between the user and kernel blobs is non-stable. Programs talk to the userspace blob and there's no guarantee of compatibility between different kernel/userspace driver versions.

This is something even Linus accepts, with the only contention that the userspace blob needs to be open source as well. They're not maintaining something in tree, that they have no way of testing without proprietary external deps.

Re:Solo – a .so loader for static Linux binaries by nextaccountic on Wednesday August 19, 2026 @09:09AM (#49361157)
> A change in paradigm is necessary. Freestanding C, not hosted C.

Or.. any other programming language. A lot of systems programming is done in Rust nowadays.

Re:Solo – a .so loader for static Linux binaries by matheusmoreira on Wednesday August 19, 2026 @09:21AM (#49361282)
Yeah. I made an entire lisp for this, and I've recently revived my Rust liblinux crate too. I've been documenting the system calls as I add them. Hopefully one day it'll rival man7 as the Linux system call reference.
Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @07:31PM (#49368562)
> Can't be done. The libc is legacy, it can't be changed without breaking everything... Every other OS forces a C runtime.

Windows never had this problem. If you really want it, you can actually skip CRT completely on Windows. Only thing you need is the initialization code that's statically linked anyway: https://nullprogram.com/blog/2023/02/15/ . You can still make Win32 calls with it. CRT is there as a convenience.

And since Linux distros are compiling everything from source anyway, this makes Linux a prime candidate for complete libc and complete ABI replacement. Thanks to stable kernel ABI, we can also use the same kernel even with Docker etc! Musl did it. Why can a completely modularized libc not?

Will it break a lot of programs in the userspace? YES! Hyrum's Law exists.

Will it be rejected by a significant part of user base? YES! They rejected systemd as well.

Will it take one or more decades to have something working? HELL YES! This is Linux we're talking about. Everybody has seen how Wayland played out. However, maybe if Valve has enough motivation to fix Linux binary problem, we maybe can get finally a binary-compatible distro in a decade or half a decade.

Re:Solo – a .so loader for static Linux binaries by stevefan1999 on Wednesday August 19, 2026 @11:55AM (#49363249)
The concept you mentioned is just dependency injection in software engineering design, but instead of giving a class and protocol/interface you give a bunch of function pointers, which is, well, some kind of interface anyway
Re:Solo – a .so loader for static Linux binaries by Root_Access on Wednesday August 19, 2026 @04:27AM (#49358667)
Most everyone else is talking about the problem while you mapped the room.

Solo is basically pg83's answer to the architecture you just described. If there is no libc independent ABI, build your own loader and shim the boundary.

I can understand Linus's obsession with taste and the areas it was overlooked or traded.

Re:Solo – a .so loader for static Linux binaries by torginus on Wednesday August 19, 2026 @06:00AM (#49359320)
Wasn't Linux Standard Base supposed to fix this? I cannot imagine any reason why glibc would break at a rate that you can't keep the current version binary compatible for years.

Or do the MS thing, and ship multiple versions like msvcrt

Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @07:19PM (#49368444)
> Wasn't Linux Standard Base supposed to fix this? I cannot imagine any reason why glibc would break at a rate that you can't keep the current version binary compatible for years.

Guess what happened with LSB? Some distros like Debian never adopted it. It also broke backwards compatibility at random times. It is now abandoned.

> Or do the MS thing, and ship multiple versions like msvcrt

MS can do that since the CRT is decoupled from the system DLL loader and Windows ABI is designed to isolated loaded DLLs into their own symbol namespaces. So your program can load DLLs that depend on a different CRT version.

Glibc's design tightly couples the system loader with the specific libc. Moreover symbols in ELF files are loaded into a single global namespace. You cannot ship shared libraries that are compiled with a different version of Glibc or Musl libc.

Re:Solo – a .so loader for static Linux binaries by torginus on Wednesday August 19, 2026 @06:08AM (#49359373)
Btw, absolutely insane that it's 2026, and Linux cannot do the most defining OS thing - that is, provide a standardized environment to run binaries against.

All solutions to this problem are hacky, complex and controversal and highly fragmented, where this should be BASIC functionality

Re:Solo – a .so loader for static Linux binaries by okanat on Wednesday August 19, 2026 @07:59PM (#49368781)
It's not insane. Many people who were in the GNU organisation wanted the OS to be as hostile against binaries as possible to prevent people distributing proprietary software with GNU. That GNU became the userspace layer.

It isn't that this is 2026 and it was a bug that hasn't been fixed since. The userspace of GNU is designed against what you consider as basic functionality.