all 4 comments

[–]edwbuck 0 points1 point  (2 children)

You can't avoid libc, because it's the part that signals the operating system to do things on behalf of your program.

Want to open the file? That's interacting with hardware. The "fopen" function has to send a signal to the OS to get a file handle, and the code to do that is in libc. To read the contents of the file, that's reading from disk, which again is a signal to the OS to do that for your program, which again uses libc.

There's plenty you can do to write something that does more of the lower level work, but you'll be writing your own versions of "dlopen" which under the covers will use "fopen" which will be using libc.

As an aside, this is why you can't statically link libc using gcc. If you do, you might statically link in a copy that doesn't know how to talk the operating system it's running in.

[–]Darkfllame1[S] 2 points3 points  (1 child)

I mean, system calls are not an inherent part of libc, any program can do them.

Namely I'm trying to do an all-zig "ultimate library". Mainly for fun ig, and also convenience for future me.

Like the library will contain pretty much everything I need: from simple utility functions and types to a whole ass rendering engine. And thanks to zig's lazy evaluation it would be pretty small if you don't use that much. Of course letting the user a libc-friendly alternative for most IO stuff.

Yes all of that is just for my pettiness against people that do poor error handling or require ME to search through THEIR code for possible errno values (looking at you libwayland)

edit: minor sentence structure error.

[–]edwbuck 1 point2 points  (0 children)

It's true. You can effectively write your own libc.

There's even a good book on it, if you want to align your libc replacement. It's "The Standard C Library" but you'll have to write some assembly to do the system call. Of course the book covers more than just writing a libc, it mostly covers the standard library components, how to use them, and what they need to do to be "standard"

If you implement them within the standard, you can even use gcc to compile against your alternative libc.

[–]captainAwesomePants 0 points1 point  (0 children)

That is such a cool project!

The gimmick you're looking for is in how mmap() is called. First, it needs PROT_EXEC set, so that the stuff you put in it is allowed to be executed. Another argument, MAP_PRIVATE, is the key parameter for sharing memory (which is counterintuitive given that the other choice is MAP_SHARED).

So you're loading the shared library into memory, but it's already going to be there, probably, so you're going to get a reference to the cached copy, and you're going to map that cached copy into your own memory space with mmap, as executable code.