5 ms·
> What would be a use-case? Maybe bootstapping a new language with no dependencies.
by guerrilla 2y ago
> What would be a use-case?
Maybe bootstapping a new language with no dependencies.
- sph 2y agoYes. Go for example doesn't use glibc and instead interfaces with syscalls directly. https://pkg.go.dev/syscall https://pkg.go.dev/syscall
- cyberpunk 2y agoI’m aware of this but I really don’t the benefits of this approach; It causes issues in eg openbsd where you can only call syscalls from libc, and it seems like they’re trying to outsmart the os developers and I just don’t see an advantage. Is it faster? More stable?
- oguz-ismail 2y ago> It causes issues in eg openbsd where you can only call syscalls from libc OpenBSD allows making syscalls from static binaries as well. If Go binaries are static, it shouldn't cause any problems.
- kbolino 2y ago> OpenBSD allows making syscalls from static binaries as well. Do you have a source for this? My Google searches and personal recollections say that OpenBSD does not have a stable syscall ABI in the way that Linux does and the proper/supported way to make syscalls on OpenBSD is through dynamically linked libc; statically linking libc, or invoking the syscall mechanism it uses directly, results in binaries that can be broken on future OpenBSD versions.
- deleted 2y ago[deleted]
- cesarb 2y ago> > OpenBSD allows making syscalls from static binaries as well. > Do you have a source for this? One article from 2019 about this can be found at https://lwn.net/Articles/806776/ https://lwn.net/Articles/806776/ (later updates https://lwn.net/Articles/949078/ https://lwn.net/Articles/949078/ and https://lwn.net/Articles/959562/ https://lwn.net/Articles/959562/). Yes, it does not have a stable system call ABI, but as long as your program was statically compiled with the libc from the same OpenBSD release, AFAIK it should work.
- oguz-ismail 2y agoYeah. Do you have any information as to how/when the OpenBSD system call ABI has changed recently? I wouldn't expect that to happen very often.
- WhyNotHugo 2y agoFrom 2019: https://lwn.net/Articles/806776/ https://lwn.net/Articles/806776/
- kbolino 2y agoIn particular, from Theo de Raadt himself: > we here at OpenBSD are the kings of ABI-instability > Program to the API rather than the ABI. When we see benefits, we change the ABI more often than the API. > I have altered the ABI. Pray I do not alter it further. The term ABI here though is a little imprecise. I believe it just refers to the syscall ABI. So, it should be possible to make an "almost static" binary by statically linking everything except libc, and that binary should continue to work in future versions of OpenBSD.
- kbolino 2y agoI upvoted for the great links, but I still don't think a static binary that will break in the future is meeting the expectations many have when static linking.
- tolciho 2y agoGo recently got run through the wringer to remove syscalls (and various Go ports are probably still broken) due to pinsyscalls.
- titzer 2y agoThere are several advantages to using kernel syscalls directly: 1. No overhead from libc; minimizes syscall cost 2. No dependency on libc and C language ABI/toolchains 3. Reduced attack surface. libc can and does have bugs and potentially ROP or Spectre gadgets. 4. Bootstrapping other languages, e.g. Virgil
- kllrnohj 2y ago> 1. No overhead from libc; minimizes syscall cost The few nanoseconds of a straight function call are absolutely irrelevant vs the 10s of microseconds of a syscall cost and you lose out on any of the optimizations a libc has that you might not or didn't think about (like memoization of getpid() ) and you need to take on keeping up with syscall evolution / best practices which a libc generally has a good handle on. > No dependency on libc and C language ABI/toolchains This obviously doesn't apply to a C syscall header, though, such as the case in OP :)
- gpderetta 2y agoA syscall can be way less than 10us. Especially if it is not doing I/O.
- kaba0 2y agoBut a kernel mode switch is definitely more expensive than a trivial (likely cached) jump instruction.
- matheusmoreira 2y ago> you lose out on any of the optimizations a libc has that you might not or didn't think about (like memoization of getpid() ) Not much of a big deal. These "optimizations" caused enough bugs that they actually got reverted. https://www.man7.org/linux/man-pages/man2/getpid.2.html https://www.man7.org/linux/man-pages/man2/getpid.2.html Because of the aforementioned problems, since glibc 2.25, the PID cache is removed: calls to getpid() always invoke the actual system call, rather than returning a cached value. Get rid of libc and you gain the ability to have zero global state in exchange. Freestanding C actually makes sense and is a very fun language to program in. No legacy nonsense to worry about. Even errno is gone.
- masklinn 2y ago> I just don’t see an advantage. You don’t have to deal with C ABI requirements with respect to stack, or registers management. You also don’t need to do dynamic linking. On the other hand all of that comes back to bone you if you’re trying to benefit from vDSO without going through a libc.
- titzer 2y ago> You also don’t need to do dynamic linking. This is a big one. Linking against libc on many platforms also means making your binaries relocatable. It's a lot of unnecessary, incidental complexity.
- rcxdude 2y agoIt also means giving up ASLR, though.
- titzer 2y agoYou can still randomize heap allocations (but not with as much entropy), as usually the heap segment is quite large. But you don't get randomization of, e.g. the code. ASLR is a weak defense. It's akin to randomizing which of the kitchen drawers you'll put your jewelry in. Not the same level of security as say, a locked safe. Attacks are increasingly sophisticated, composed of multiple exploits in a chain, one of which is some form of ASLR bypass. It's usually one of the easiest links in the chain.
- LegionMammal978 2y ago> On the other hand all of that comes back to bone you if you’re trying to benefit from vDSO without going through a libc. At least the vDSO functions really don't need much in the way of stack space: generally there's nothing much there but clock_gettime() and gettimeofday(), which just read some values from the vvar area. The bigger pain, of course, is actually looking up the symbols in the vDSO, which takes at least a minimal ELF parser.
- 2y ago
- SAI_Peregrinus 2y agoGNU aren't the OS developers of the Linux kernel. Think of the Go standard library on Linux as another libc-level library. On the BSDs there is a single libc that's part of the OS, on Linux there are several options for libc.
- josefx 2y agoDidn't they go back to Glibc in 2017 after a syscall silently corrupted several of their tightly packed tiny Go stacks? The page you link to seems to refer to a proposal from 2014 as "new".
- melodyogonna 2y agoThat is the documentation for the Go syscall package. If you scroll down to the bottom of the page you'll see links to the source files.
- jsheard 2y agoIIRC that was specifically on macOS and other BSDs which don't have a stable syscall interface. They still use raw syscalls on Linux, which guarantees syscall stability on pain of Linus Torvalds yelling at you if you break it.
- titzer 2y agoI'm 100% with Linus on this one.
- favorited 2y agoLinus ships a kernel –– where would his stable interface live if not the syscall ABI? The *BSD and macOS folks ship operating systems, where they have the option of defining their ABI at a higher level of abstraction.
- matheusmoreira 2y agoLinux could have made their own libc and mandated use of it. But they didn't. They chose a language agnostic binary interface that's documented at the instruction set level. As a result of that brilliant design choice, every single language can make Linux system calls natively. It should be simple for JIT compilers to generate Linux system call code. No need to pull in some huge C library just for this. AOT compilers could have a linux_system_call builtin that just generates the required instructions. I actually posted this proposal to the GCC mailing list.
- asveikau 2y agoExcept there are some platforms where you need to go through libc and the direct syscall interface is considered private, or subject to change. OpenBSD is like this, and I believe Mac is too.
- matheusmoreira 2y agoLinux is the only one that is not like this. I wrote an article about the subject: https://www.matheusmoreira.com/articles/linux-system-calls https://www.matheusmoreira.com/articles/linux-system-calls
- vetinari 2y agoWhile Linux does have stable syscall interface, unlike other OS-es, you still want to go through glibc. At least for NSS, otherwise your app could be broken. Golang has CGO_ENABLED=1 as the default for this reason.
- boomskats 2y agoWorth mentioning that the golang.org/x/sys/unix package has better support for syscalls than the og syscall package nowadays, especially for some of the newer ones like cachestat[0] which was added to the kernel in 6.5. AFAIK the original syscall package was 'frozen' a while back to preserve backward compatibility, and at one point there was even a bit of drama[1] around it being marked as deprecated instead of frozen. [0]: https://github.com/golang/go/issues/61917 https://github.com/golang/go/issues/61917 [1]: https://github.com/golang/go/issues/60797 https://github.com/golang/go/issues/60797
- lpapez 2y agoUndeprecating something is truly a rare sight. So far I only knew about PHP undeprecating "is_a" function, so I guess this puts Go in good company ^^
- jcalabro 2y agoIndeed, Zig does this for instance (at least for x86_64 linux [0]) as a way to avoid having to link libc at all [0] https://github.com/ziglang/zig/blob/ee9f00d673f2bccddc2751c328758a2820d2bb70/lib/std/os/linux/x86_64.zig https://github.com/ziglang/zig/blob/ee9f00d673f2bccddc2751c3...
- matheusmoreira 2y agoI've been working on that language for a while now! https://github.com/lone-lang/lone https://github.com/lone-lang/lone It's a lisp interpreter with a built in system-call primitive. The plan is to implement everything else from inside the language. Completely freestanding, no libc needed. In the future I expect to be able to boot Linux directly into this thing. Only major feature still needed for kernel support is a binary structure parser for the C structures. I already implemented and tested the primitives for it. I even added support for unaligned memory accesses. Iteration is the only major language feature that's still missing. I'm working on implementing continuations in the interpreter so that I can have elegant Ruby style iteration. This is taking longer than expected. This interpreter can make the Linux kernel load lisp modules before its code even runs. I invented a self-contained ELF loading system that allows embedding arbitrary data into a loadable ELF segment that the kernel automatically maps into memory. Then it's just a matter of reaching it via the auxiliary vector, The interpreter uses this to automatically run code, allowing it to become a freestanding lisp executable. I wrote an article about how it works here: https://www.matheusmoreira.com/articles/self-contained-lone-lisp-applications https://www.matheusmoreira.com/articles/self-contained-lone-...
- samatman 2y ago> I'm working on implementing continuations in the interpreter You might find this paper (and everything else on the site) interesting and relevant. https://okmij.org/ftp/continuations/ZFS/context-OS.pdf https://okmij.org/ftp/continuations/ZFS/context-OS.pdf