News for hackers. Stuff that matters.
Re:Actually Portable Executables by jart on Sunday February 28, 2021 @06:17AM (#26292539)
Cosmopolitan Libc author here. When I saw this article earlier today, it put a big smile on my face, because I would have thought there'd be so many more issues than there turned out to be! For additional context, we've got a GitHub issue that's tracking progress on the changes that need to be made based on what we learned: https://github.com/jart/cosmopolitan/issues/61
Re:Actually Portable Executables by shawxe on Sunday February 28, 2021 @11:53AM (#26294675)
So first of all, I just want to echo the general sentiment here and say that all of this is beyond awesome. Cosmopolitan libc seems to have the potential to literally re-define what constitutes portable code.

With that out of the way, am I understanding correctly that the way this works on Linux/Unix is that the modifies itself (by overwriting the EXE file header with an ELF header)? This seems to have the consequence of making that specific file no longer portable. If I'm understanding things correctly, it also looks like the QEMU hack for non-x86_64 architectures will only work once per file, since after the first time running the file it will no longer run as a shell script on Unix so the QEMU invocation will be unreachable.

Have you considered adding workarounds for this?

Re:Actually Portable Executables by p10jkle on Sunday February 28, 2021 @07:03PM (#26298316)
On unix its a Thompson shell script that pipes an ELF binary to 'exec', I believe
Re:Actually Portable Executables by ahgamut on Sunday February 28, 2021 @04:13PM (#26297120)
I'm the author of the blog post!

As someone who has never messed around with Libc-level programming, it was surprisingly straightforward (and exciting!) to compile Lua all the way.

Cosmopolitan is incredible, thank you so much.

Re:Actually Portable Executables by egeozcan on Sunday February 28, 2021 @08:40AM (#26293336)
Only your own creativity seems to match your intelligence; excellent, excellent work!

I was wondering if we can accompany runtimes written in C (like lua) with some scripts? So we have cross-platform, double-click-to-run scripting?

For us poor souls who can't write reliable C code, that would be a great thing!

Re:Actually Portable Executables by jart on Sunday February 28, 2021 @09:02AM (#26293471)
Yes we can do that. There's a real opportunity here to define a novel API / framework on top of Cosmopolitan that does just that. It's something I myself have personally refrained from, mostly because fiddling with the low level bits is what I'm best at, and novel APIs require a certain kind of artist. But I'm certain that someone if not myself at some point is going to come along and use Cosmo for that purpose and it'll be pretty cool.
Re:Actually Portable Executables by mikewarot on Sunday February 28, 2021 @07:23AM (#26292884)
I'm an old Delphi/Pascal application programmer here, trying to get the lay of the land in the C/C++ world.

Why is there a forest of files in Cosmopolitan Libc? I tried looking at it on Github to see how things were done, and there were a lot of .h and .S files, I couldn't actually find the C source, though I'm sure somewhere in there is a .c file.

Doesn't fragmenting the source into thousands of files make compilation far slower than it needs to be?

Also, I wonder if/how functions that aren't called in a program get trimmed away by the linker, and thus don't make the executable larger.

Re:Actually Portable Executables by jart on Sunday February 28, 2021 @07:44AM (#26293009)
It takes about 18 seconds to build the entire Cosmopolitan repo and run all its unit tests on my PC. During that time the make command builds 14,376 .o files, 66 .a archives, and 421 .com executables. It's an exceedingly fast build config.

Having lots of objects is a good thing because it helps static linking work better. When the Unix linker loads a symbol from a static archive, it pulls in the whole module that defines that symbol. For example, if you define memcpy() and memset() in the same .c file and then your app only needs one of them, they'll both go towards bloating your binary. Workarounds exist like -ffunction-sections and -Wl,--gc-sections but a C library should make assumptions about the fewest flags feasible.

What's the end result? We're able to build executables that are 12kb in size which run on seven different operating systems. The big codebase is what made tiny binaries possible: https://justine.lol/cosmopolitan/howfat.html

Re:Actually Portable Executables by matheusmoreira on Sunday February 28, 2021 @08:22AM (#26293241)
Do you build on tmpfs? I started doing that and it makes builds ridiculously fast. $XDG_RUNTIME_DIR is perfect for this, I just make a directory there and symlink the build directory to it. Even added some makefile logic to ensure the link target exists:

  build_directory_link := $(shell readlink $(build_directory))
  $(if $(build_directory_link),$(shell mkdir -p $(build_directory_link)))
Re:Actually Portable Executables by ed25519FUUU on Sunday February 28, 2021 @09:56AM (#26293786)
Good optimization, thanks for the pointer!
Re:Actually Portable Executables by matheusmoreira on Sunday February 28, 2021 @09:30PM (#26299101)
It also reduces wear on storage devices. Why write temporary build artifacts to permanent memory after all? Gotta use those 32 GB of RAM for something.

Linux will automatically cache all source files in RAM because of the page table cache. Writes to slow storage devices are eliminated through tmpfs. Amazing really.

Re:Actually Portable Executables by wyldfire on Sunday February 28, 2021 @12:02PM (#26294757)
Also, if you are using BFD ld, you should consider gold or lld. Significantly faster if the link is the slow step.

Also much lower peak memory usage for lld, which is great if you have multiple concurrent link steps.

Re:Actually Portable Executables by krab on Sunday February 28, 2021 @08:14AM (#26293193)
May I ask - what was the reason for creating APE/Cosmopolitan?

I read your post about actually portable executable format but I wonder if it's something that you found immediately helpful for some project or if you work on it just out of curiosity.

Re:Actually Portable Executables by moonchild on Sunday February 28, 2021 @04:04PM (#26297046)
> Doesn't fragmenting the source into thousands of files make compilation far slower than it needs to be?

This allows incremental compilation to work much better than it otherwise would. Your first clean build may be slightly slower, but after that, you only have to recompile the files you change.

Re:Actually Portable Executables by simias on Sunday February 28, 2021 @10:51AM (#26294183)
Compiling ASM and even C is very fast these days. No generics, small compilation units etc... Even with optims it's usually a non issue in my experience.

For a datapoint it takes me ~2 minutes to build a reasonably fully featured ARM linux kernel with a cold cache on a 5 year old i5. wc counts 1399 CC, 65 AS and 411 LD calls. And of course incremental rebuilds are only a fraction of that.

Re:Actually Portable Executables by HexDecOctBin on Sunday February 28, 2021 @09:43AM (#26293706)
One question: is it possible to load .so files (through dlopen/dlsym) on Linux when compiling to APE?

I was working on something similar (though much smaller in scope), but had to stop when I realised that `ld-linux.so` has some internal APIs that Glibc uses to setup dlopen()/dlsym(); essentially meaning that it is very hard -if not impossible - to load any shared libraries if one does not link to Glibc.

What I wouldn't give for a liblinux, similar to NTDLL.

Re:Actually Portable Executables by matheusmoreira on Sunday February 28, 2021 @09:59PM (#26299270)
> What I wouldn't give for a liblinux, similar to NTDLL.

Hey I actually tried to make such a thing.

https://github.com/matheusmoreira/liblinux

It provides access to Linux system calls and process start up code that gets all the arguments, environment and auxiliary values. I have several examples of applications written in 100% freestanding C with zero dependencies other than this library:

https://github.com/matheusmoreira/liblinux/tree/master/examp...

It's a bit too low level but I actually planned to make my own ld-liblinux eventually. It currently works with static and dynamic linking. The ld-linux.so is able to link even though nothing else links against glibc. I didn't test dynamic loading though.

I stopped working on it because I found better solution for system calls on the Linux kernel repository:

https://github.com/torvalds/linux/blob/master/tools/include/...

Do you think liblinux could have a future?

Re:Actually Portable Executables by HexDecOctBin on Monday March 01, 2021 @06:09AM (#26301603)
> I found better solution for system calls

Yeah, I have seen that file. Thought last I checked, it crashes in certain conditions [1]; I didn't really go back to it to fix it.

> I actually planned to make my own ld-liblinux eventually

Can you share this code? If not, could you document how exactly would you have done this? I lost all motivation once I realized that ld-linux and Glibc communicate with private APIs, but I'd love to actually work on it if it was possible to do this.

> Do you think liblinux could have a future?

Absolutely. The problem with Linux currently is that the loader rejects programs at the sign of slightest incompatibility before even trying to execute them, which means that there is nothing that the application code could do to work around said incompatibility. If we were able to get our code running (or, as I like to say it, make %RIP point inside the main function), we could then do whatever hacky-bullshit was required make the software work. All I need is to get our code executing, and from that point on, I'll handle system compatibility.

[1]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95411

Re:Actually Portable Executables by matheusmoreira on Monday March 01, 2021 @07:07AM (#26301951)
Not sure why the stack is unaligned there. The way I solved this in liblinux is to just pass the stack pointer to a C function and compute all the other pointers there. That way the compiler deals with the stack stuff.

  _start:
      xorq %rbp,%rbp    /* user code should mark the deepest stack frame
                         * by setting the frame pointer to zero
                         */

      movq %rsp,%rdi

      call liblinux_start

      movq %rax,%rdi
      movq $__NR_exit,%rax
      syscall

  static void *after(void *vector) {
      void **pointer = (void **) vector;
      while (*pointer++ != 0);
      return pointer;
  }

  int liblinux_start(void *stack_pointer) {
      long count;
      char *arguments;
      char *environment;
      struct auxiliary *values;

      count = *((long *) stack_pointer);
      arguments = ((char **) stack_pointer) + 1;
      environment = arguments + count + 1;
      values = after(environment);

      /* start is the main function */
      return start(count, arguments, environment, values);
  }
> Can you share this code? If not, could you document how exactly would you have done this?

Unfortunately I didn't make it that far. I was planning to study how glibc and musl do it just like how I studied their system call implementations. If I start working on this again I'm gonna look this up. I'll need to learn this linking stuff in order to support the kernel vDSO anyway.

Re:Actually Portable Executables by surajrmal on Sunday February 28, 2021 @12:12PM (#26294857)
It doesn't appear to be supported in their libc implementation:

https://github.com/jart/cosmopolitan/blob/d7ac16a9ed56ebdc70...

Re:Actually Portable Executables by HexDecOctBin on Monday March 01, 2021 @06:12AM (#26301628)
Yeah, as I feared. Some one needs to wrest the control of ld-linux.so from Glibc's hands and give it to the Kernel developers (who "will not break userspace"). Otherwise, Linux will always be a all-work-for-no-reward platform.
Re:Actually Portable Executables by surajrmal on Sunday February 28, 2021 @12:20PM (#26294951)
Looks like you're also giving up position independent code as that also relies on the dynamic linker.
Re:Actually Portable Executables by RodgerTheGreat on Sunday February 28, 2021 @11:57AM (#26294721)
Have you considered writing an index for Cosmopolitan's API by topic? The current reference documentation is rather daunting, and it is very difficult to determine at a glance what sorts of functionality are available, and thus what kinds of applications could be written or ported.

What would it take to create an analog of SDL- some kind of lowest-common-denominator interface for mouse/keyboard io, audio output, and software-rendered graphics?

Re:Actually Portable Executables by jart on Friday March 05, 2021 @05:17PM (#26362896)
Cosmopolitan is a C library that makes an effort to conform to POSIX and ANSI standards. So in addition to its documentation page, you can dust off any old textbook on C development and use that as a reference or tutorial.

Something like SDL could be ported to run on top of Cosmopolitan but we'd need to port all its dependencies too. That would be a massive undertaking. If Cosmopolitan ends up being the next big thing and attracts a large community of contributors then something like that is bound to happen. Right now it's just a scrappy ambitious project being built for fun. So GUIs aren't something we're able to do quite yet. Although we've got TUIs working great! You can have the best most portable console / terminal apps in the world, today.

Think about it this way. How many years did it take Microsoft and Linux before they could offer a polished GUI? That should give you a rough estimate of how long it takes to develop these sorts of things from first-principles.

Re:Actually Portable Executables by ducktective on Sunday February 28, 2021 @06:24AM (#26292571)
Any recommendations to somebody who wants to learn C "properly" in $CURRENT_YEAR?
Re:Actually Portable Executables by CraigJPerry on Sunday February 28, 2021 @08:58AM (#26293446)
https://www.oreilly.com/library/view/21st-century-c/97814919...

I thought 21st Century C was good, i've still kept my copy. I'd happily recommend it.

I like the K&R book too - it feels reeeeeeally old but it's really short.

There's a few others that have helped me in various ways but these are a little older -

Love C by Tim Love (free online, my copy is something i just printed out, it's not that long).

Programming from the Ground Up (x86 assembly) - this is available freely online but i bought the book and that helped me a lot with C even though it's a book with only assembly... (to be fair, it does go through calling conventions).

Finally there's another book i love, Advanced Programming in the Unix Environment by Stevens, i have the 6th edition updated by Rago after Stevens' passing. Fascinating book - but huge.

Re:Actually Portable Executables by jtvjan on Sunday February 28, 2021 @06:42AM (#26292664)
I really liked "The C Programming Language (second edition)" by Kernighan & Ritchie. It doesn't teach C99 and later features, but if you want to write portable code you're not using those anyway.
Re:Actually Portable Executables by e12e on Sunday February 28, 2021 @08:56AM (#26293434)
From various discussions on Hn, I think the consensus is most people really like k&r as a technical book (it's concise, clear and a fun read) - but everyone working with C says its a terrible book for learning modern C.

I tried to refresh my memory from previous threads, and I think the general trend has been to recommend (as seen in sibling comments):

https://modernc.gforge.inria.fr/

https://nostarch.com/Effective_C

I've also seen the older:

https://www.oreilly.com/library/view/21st-century-c/97814493...

Mentioned.

There's also Architecture of Open Source Applications, which can help with starting to read some larger code bases, some of which are in C: http://aosabook.org/en/index.html

And there's a general recommendation to go read the source code of the Redis cache/db.

Finally i came across a mention of this short article on gdb (nb: mention of TUI text ui should probably have been in the top, not a foot note):

https://www.recurse.com/blog/5-learning-c-with-gdb

I feel I'm missing a book that has come up often, but can't think of which one.

I did like zed Shaws learn c the hard way, but I'm afraid it's getting a bit long in the tooth: https://learncodethehardway.org/c/

Re:Actually Portable Executables by sillysaurusx on Sunday February 28, 2021 @08:22AM (#26293239)
K&R is a horrible way to learn C. It's the best way to make someone run in the other direction, though.

It's like telling someone that SICP is the best way to learn Scheme. Maybe, but lots of people learn differently.

Unfortunately I don't have good suggestions myself, but at least they won't feel bad if K&R isn't their cup of tea.

Re:Actually Portable Executables by kamranjon on Sunday February 28, 2021 @11:45AM (#26294599)
I am just trying to learn myself so take this with a grain of salt but I have found the github of Antirez:(https://github.com/antirez) - the author of Redis - to be an amazing resource. The code is incredibly well documented and to my eyes pretty well written. A good place to start I think is Kilo:(https://github.com/antirez/kilo/blob/master/kilo.c) - a 1000 line text editor with no dependencies.
Re:Actually Portable Executables by himujjal on Sunday February 28, 2021 @09:16AM (#26293544)
APE makes it viable for a cross platform C library with a cross platform C compiler to make cross platform binaries.

Besides I was in the same boat as you. I come from the world of JS/Python/Go. I even wrote https://github.com/Himujjal/ekon in pure C recently. The reason I thought C would be good is performance and portability. But I found it to be better to invest time in Rust rather than in C. C is a fantastic language but cross platform dependency management is difficult. Unit Testing is also difficult. There are solutions but not as efficient as Rust's ecosystem.

BTW I wish there could be a Cargo for every language.

Re:Actually Portable Executables by moonchild on Monday March 01, 2021 @04:00AM (#26300861)
> C is a fantastic language

Odd...I find that a very strange sentiment.

I thoroughly enjoy C, and have even written a compiler for it, but I don't think it's a well-designed language by any account.

Re:Actually Portable Executables by alisonatwork on Sunday February 28, 2021 @11:20AM (#26294387)
I can't remember where I learned the basics, but if you aren't new to programming in general then I think there are only three important things you need to know: what is a pointer, what is a macro, and always free what you malloced. Reading a book or tutorial will be helpful for this. In my day it was K&R, no doubt there are more up-to-date ones now.

But the next step, which I think is far more important, is to look at the source code of tools that you actually use in real life. Things like cp, or wc, or head. You've probably used them for years without thinking about it, but they're all written in C. Don't look at the modern GNU versions just yet, since they can be packed full of complex functionality, start with micro implementations like Busybox or Toybox. Then look at some OSes that are known for super clean code like NetBSD or OpenBSD. In those OSes you have the benefit of being able to go back to the version that existed 25+ years ago, so you can read through the diffs to see how they adopted new features and found new ways to address C's biggest flaw/risk - memory exploits.

If you're interested in kernel programming, check the Linux and BSD sources, and lurk on the mailing lists for a while to see how people talk about the code. The review process tends to be a bit more brusque than you might be used to on Github, but it's often detailed and results in code that is of a relatively high quality, or at least a consistent standard. It's a great place to learn.

Re:Actually Portable Executables by vkazanov on Sunday February 28, 2021 @06:43AM (#26292673)
Try new books: effective c and the free modern c one. They actually teach the language and all the concepts.
Re:Actually Portable Executables by asicsp on Sunday February 28, 2021 @07:55AM (#26293067)
Re:Actually Portable Executables by vkazanov on Sunday February 28, 2021 @01:49PM (#26295927)
Yup
Re:Actually Portable Executables by ktr on Sunday February 28, 2021 @11:19AM (#26294381)
Re:Actually Portable Executables by dj_mc_merlin on Sunday February 28, 2021 @07:24AM (#26292893)
K&R -> do some random programming problems -> small project -> learn ASM -> learn how to do a buffer overflow (read "Smashing the stack for fun and profit") -> from here find your own path.

The first three are just useful for getting the basics. The next two are for starting to learn low level stuff. You don't really understand C until you understand how it relates to lower level code.

Re:Actually Portable Executables by unkulunkulu on Sunday February 28, 2021 @06:35AM (#26292631)
$CURRENT_BEST_BOOK Sorry :)
Re:Actually Portable Executables by CodeArtisan on Sunday February 28, 2021 @09:41AM (#26293688)
C Primer Plus by Stephen Prata is the most complete i have seen, it does cover everything up to C11 and goes in details about stuff like array vs pointer.

I don't like 21st Century C, it may have changed since then but it has a chapter titled "Object-Oriented Programming in C" which is confusing object with Abstract data type.

Re:Actually Portable Executables by edgyquant on Sunday February 28, 2021 @12:43PM (#26295179)
I assume object oriented C means using structs and function pointers?
Re:Actually Portable Executables by CodeArtisan on Sunday February 28, 2021 @04:21PM (#26297181)
No. For 21st Century C, an "object" is an incomplete type and procedures.

    struct Object;
    void Object_init(struct Object *o);
That's ADT.
Re:Actually Portable Executables by e12e on Sunday February 28, 2021 @02:29PM (#26296266)
Not sure if it's been mentioned, but the logical next step would seem to be extending the zip hack[1] to allow embedding lua source with the binary?

[1] https://news.ycombinator.com/item?id=26271117

Re:Actually Portable Executables by s_Hogg on Sunday February 28, 2021 @08:23AM (#26293250)
Congratulations on all you've done so far, it's amazing.
Re:Actually Portable Executables by lostmsu on Sunday February 28, 2021 @12:53PM (#26295279)
Copy-pasted from thread about libc:

I missed an opportunity to ask in the previous thread: what would it take to link an app in a different language (say, Rust) with this library? Is it enough to just build an object file, that has libc functions assuming LP64 ABI as unresolved exports?

Re:Actually Portable Executables by jll29 on Monday March 01, 2021 @12:00AM (#26299889)
Amazing accomplishment, a great hack!
Re:Actually Portable Executables by stephc_int13 on Sunday February 28, 2021 @11:02AM (#26294258)
In my opinion, the most important drawback to your work and its adoption is the use of fancy unicode characters in the name.

I think your work is outstanding but it looks a bit childish/bizarre with this name, and thus it might prevent some people to trust its reliability.

Re:Actually Portable Executables by chacha2 on Sunday February 28, 2021 @11:15AM (#26294351)
Naming Your Child | David Mitchell's Soapbox

https://www.youtube.com/watch?v=Xblh12XgQ4o

The first half is relevant.

Re:Actually Portable Executables by lordofgibbons on Sunday February 28, 2021 @11:11AM (#26294319)
The future is now, old man
Re:Actually Portable Executables by metalliqaz on Sunday February 28, 2021 @11:11AM (#26294318)
you must mean ape. But the package itself doesn't seem to use any such characters.