For some time, I have been discomfited by operating systems putting requirements to run specific userspace code onto arbitrary programs.
Sure, some amount of startup code usually exists; even C has to cons up the arguments to `main`, after all. And of course, to execute a system call or access some OS-provided object, allocate memory, and so on, requires some kind of contractual interface with the OS.
But that's not what I'm referring to. It's things like libraries colluding to implement a non-trivial amount of functionality of some system call behind the caller's back, or requirements to use a specific userspace library, calling convention, memory allocator, etc.
Why? Because this limits flexibility for user software, by conflating mechanism and policy. The universe of interesting and useful user programs is vast; by imposing requirements to (say) make system calls through a particular library interface, I'm imposing a particular "shape" onto the design space for the programs that use my system, and thus, pruning away some subset of programs from working on my system.
Consider programming languages: in the context of function calls, they do not all use the same conventions for argument passing and returning values, with respect to stack and register usage. To mandate that proper use of the system must use some specific calling convention (as opposed to system call invocation convention, which is a clear interface boundary) puts a burden on the language implementers and constrains their design space. It shouldn't be necessary to obey all of the rules of the conventions of `libc` to successfully use a system in a program not written in C.