|
|
Subscribe / Log in / New account

A way out for a.out

By Jonathan Corbet
March 24, 2022
The a.out executable format dates back to the earliest days of Linux — and before. It has not been used in any serious way for decades, but support still exists in the Linux kernel and has resisted all attempts at its removal. Back in January, Borislav Petkov tried yet again to delete support for this format, leading to another extended discussion. There is one difference this time around, though: the effort to get rid of a.out support might just succeed.

The a.out format dates back to the first edition of Unix. When MINIX came along, it naturally used that format for its executable files; that, in turn, led to a.out being used in Linux as well. It is a simple format, and its implementation on Linux was even simpler; among other things, every Linux shared library had to be centrally assigned its own portion of the address space, since libraries could not be relocated at run time. Still, Linux used a.out for some time, until support for the newfangled ELF format was first added to the 0.99.13 development kernel in 1993.

There was a time when the crazier people among us manually converted our Slackware systems from a.out to ELF in order to be able to try it out and gain the benefits before distributions were updated. They still bear the scars from that time. Not that your editor would ever admit to knowing anybody who would have engaged in any such activity.

ELF has been the standard executable format for Linux on most architectures since 1995. One might think that would have provided enough time for any users of a.out binaries to grudgingly move on to ELF; its adoption can probably be judged to not be a passing fad at this point. But, in the real world, surprises lurk.

The initial conversation on removing a.out faded out fairly quickly, but was restarted when Eric Biederman posted a patch disabling the building of a.out support on the two architectures (Alpha and m68k) that still enable it by default. This patch did not actually remove the support, it just turned it off to see if anybody would scream. If protests were raised, support could be turned back on quickly and easily; otherwise a full removal could be done.

Linus Torvalds quickly responded that he was "pretty sure we can't do this". He pointed out that the native executable format on Alpha systems running Digital's Unix was essentially a.out, even if it went by the newer name of ECOFF. The Linux a.out loader can run ECOFF programs by virtue of ignoring some of the newer ECOFF features; taking it out would break any systems still using that support. One might think that the number of users who are still using Alpha CPUs, running ECOFF binaries on those CPUs, and tracking current kernel releases might be a fairly small number, but one never knows.

Kees Cook did do a little research on, seemingly, the only distribution that still supports Alpha (Gentoo) and found that the only ECOFF files present contained firmware, which does not run on the CPU anyway. He concluded that there would be no harm from removing a.out support on this platform: "Let's do it".

It seems to be a universal rule that somebody always has to come along to ruin the party. In this case, just as it seemed like there were no further obstacles to the removal of a.out, James Jones showed up to let it be known that he was still using a.out:

The use case is running an old set of tools to build programs for the Atari Jaguar. Namely, Atari's assembler (mac) and linker (aln). The alternative is running windows versions in dosbox, or using some replacements that have been developed based on an even older, less-featureful version of the source code for mac and aln, but which still haven't managed to add back in all the features needed to build some programs or use the Atari debugging tools (Also available in a.out only).

He gave some more details on why he still needed to use these tools in this followup message

Moving a program to a new executable format is normally just a matter of rebuilding the program. But rebuilding is a rather more difficult task in the absence of the source code. Finding oneself stuck trying to run a decades-old binary on modern systems is just one of the many joys reserved for users of proprietary software — but many people have found themselves in that position at one time or another. They are legitimate Linux users, and there is no desire to break their systems. So Petkov duly gave up and asked only that Jones document his usage of a.out for the benefit of those who might try to remove it in the future.

Cook, however, was not so quick to throw in the towel; he looked at the programs in question and concluded that it might be possible to write an ELF wrapper program that could load and run old a.out binaries. One day later, he posted such a program, noting that it could run the aln program at least far enough for it to complain about its command-line arguments. Jones tried it out and was pleased with the results:

Yes, works perfectly, thank you. I like the idea of using this much better than getting emailed every time someone wants to delete the a.out code again. Consider my use case withdrawn. I've already pushed an update to my jaguar-sdk project to use this tool instead.

So removal of a.out support is back in the plans for the 5.18 kernel. Perhaps the effort will succeed this time, though there are still no guarantees; there may be a.out users who are unaware of the coming apocalypse and haven't yet made their objections known. If those users are unable or unwilling to use Cook's wrapper utility, the excision of a.out support may, once again, have to be deferred to some future kernel release.

Index entries for this article
Kernela.out


to post comments

A way out for a.out

Posted Mar 24, 2022 15:50 UTC (Thu) by dullfire (guest, #111432) [Link]

If cook didn't take this approach: then making the wrapper be a binfmt_misc tool (and having a libre license) would probably be the most forward compatible. After all there's no reason an interpreter (ld.so) couldn't parse all the a.out binaries and libs in question, and then relocate itself out of the way before constructing the final run-time image.

Or, if the programs properties were just right, you could get even fancier and convert the program to elf (of course you could not take advantage of elf features) in memory, before actually "exec-ing" it.

A way out for a.out

Posted Mar 24, 2022 16:09 UTC (Thu) by wtarreau (subscriber, #51152) [Link] (20 responses)

And I thought I was using old stuff...

$ cat /proc/version
Linux version 2.4.37-wt1-utm10.1-alix (willy@wtap) (gcc version 3.3.6) #1 Tue Dec 9 12:50:07 CET 2008

Waiting for this PC-Engines ALIX to die but it doesn't want to. It has only known ELF anyway, I migrated to ELF with kernel 2.0 (except for floppy disks for which I kept the smaller a.out a bit longer).

Jonathan, like you I was one of those installing libc.so.4 and libc.so.5 side by side on Slackware to try to figure if ELF would bring anything (by then it only brought slightly slower program execution IMHO but it was the future). Not everything worked out of the box, but overall it used to be much more seamless than the following migration to glibc2 where the low-level network API completely changed and required many network programs to be heavily modified!

A way out for a.out

Posted Mar 24, 2022 16:38 UTC (Thu) by corbet (editor, #1) [Link] (4 responses)

And here I'd thought I had successfully suppressed the painful memories from the glibc2 transition...thanks a lot, man...:)

A way out for a.out

Posted Mar 24, 2022 16:43 UTC (Thu) by smoogen (subscriber, #97) [Link]

Oh no.. you already triggered flashbacks for many of us. You get to watch us crawl around with our terror weighted blankets for a week or so. Then someone will go over the changeover from libc5 to libc6, and we can start all over again.

A way out for a.out

Posted Mar 25, 2022 11:46 UTC (Fri) by jd (guest, #26381) [Link] (2 responses)

*cackles with glee, knowing how to bring up the most traumatic memory of that era*

Anyone remember the problems involving Gnu Make during that transition?

A way out for a.out

Posted Mar 26, 2022 4:54 UTC (Sat) by wtarreau (subscriber, #51152) [Link] (1 responses)

> Anyone remember the problems involving Gnu Make during that transition?

I don't remember problems *specific* to that transition, GNU Make broke something with *every single minor update*. For more than 10 years I've had to have a collection of 3.77, 3.79, 3.80, 3.81, 3.82 and 3.83 on my machines and chose the working one depending on what I was trying to build :-/ It seems to have stabilized a bit since 4.1 or so, let's keep fingers crossed.

A way out for a.out

Posted Mar 28, 2022 23:15 UTC (Mon) by anonymous_commenter (guest, #117657) [Link]

Let’s see ummm…

Debian 1.3 —> Debian 2

There was also, many blue moons ago, the transition from nsswitch et al to libpam. That one was worse for me.

A way out for a.out

Posted Mar 24, 2022 18:33 UTC (Thu) by hrw (subscriber, #44826) [Link] (12 responses)

Nice!

Alix was fun platform. That Geode LX cpu which was either 586 or 686 depending who asked.

Always can run newer stuff but having system running so old software i would keep it alive until death (their or mine).

A way out for a.out

Posted Mar 24, 2022 22:51 UTC (Thu) by nix (subscriber, #2304) [Link] (11 responses)

My Soekris net5501 firewall is still running. Geode LX, again :)

(I really must replace it one of these days: having a single point of failure that is 13 years old is worrisome. I have a Turris Omnia I keep meaning to set up, but the new system is so crazy weird I haven't dared to try to actually replace it yet. It's a shame nobody makes anything like the net5501 with lots and lots of network ports any more :( I need at least five...)

A way out for a.out

Posted Mar 25, 2022 1:31 UTC (Fri) by pabs (subscriber, #43278) [Link]

You can install other distros on the Turris Omnia, but there are some caveats of course. The install guide for Debian is here (might need some updates):

https://wiki.debian.org/InstallingDebianOn/Turris/Omnia

A way out for a.out

Posted Mar 25, 2022 6:37 UTC (Fri) by hrw (subscriber, #44826) [Link]

There are many miniPC models on Chinese market.

https://www.aliexpress.com/item/1005003174267310.html has 6 ports each with Intel i211 network card.

I use similar 4 port one with OpenWRT as a router. Works fine.

A way out for a.out

Posted Mar 25, 2022 7:33 UTC (Fri) by pbonzini (subscriber, #60935) [Link]

The Turris MOX is extensible, you can add groups of 8 network ports (plus a WAN port with optional support for PoE). If you add more than 8, however, ports from separate groups will go through a 2.5 Gbps switch. I suggest not buying the batteries included versions, and instead getting all the modules you need separately. This way you have 1 GiB of memory instead of 512 MiB.

A way out for a.out

Posted Mar 25, 2022 10:14 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link] (2 responses)

A way out for a.out

Posted Mar 25, 2022 12:49 UTC (Fri) by nix (subscriber, #2304) [Link] (1 responses)

They're tempting... but RouterOS, well, how shall I put it, I've had it up to here with vendor-supported crazy operating systems. I want something that can run normal Linux like the Soekris always could, thankyouverymuch (and now it seems the Turris Omnia I've already got can! so I'll try that ;) )

A way out for a.out

Posted Mar 25, 2022 12:58 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

I had an RB from them earlier that I used for OpenWRT. But I've recently tried RouterOS and I was pleasantly surprised, it just works and the UI is very pleasant. Mikrotik also supports hardware for at least 10 years, so I can just turn on automatic updates and be sure the software will be kept up-to-date.

They recently added Docker support and it allowed me to scratch the last itch, to host my own version of speedtest to easily monitor the WiFi performance (https://github.com/librespeed/speedtest).

A way out for a.out

Posted Mar 28, 2022 21:48 UTC (Mon) by abufrejoval (guest, #100159) [Link] (4 responses)

This one recently reviewed on ServeTheHome falls one port short, but if you insist on Linux (vs. pfSense/BSD) you can add another RealTek 8156 base USB3 2.5 Gbit/s NIC.

Actually with USB3 NICs, just about any board will do, even if lack off offload support may require more CPU power.

I've been using a 8-port Jetway NF592-Q170 with a Kaby Lake i7-7700T for a few years, but that's a slightly different price (and performance) point.

A way out for a.out

Posted Apr 11, 2022 21:29 UTC (Mon) by nix (subscriber, #2304) [Link] (3 responses)

USB3 NICs are *that fast* nowadays, and reliable enough for serious use? I'm frankly amazed. I always thought of them as being slow and buggy and prone to introducing fairly frequent spurious corruption into the data stream (I mean the protocol clearly has no useful error checking, given how easy it is for me to cause external disk corruption on one of my Chromebooks by just using an external monitor and the USB port next to the monitor port for mass storage at the same time).

But maybe I've been misled by the raspberry pi's famously terrible USB ports :)

A way out for a.out

Posted Apr 12, 2022 9:46 UTC (Tue) by farnz (subscriber, #17727) [Link] (1 responses)

USB High Speed or USB Super Speed? High speed (480 Mbit/s) has a CRC-5 to protect packet headers, and a CRC-16 to protect the data, while Super Speed (5 Gbit/s or above) uses the same CRC-32 as Ethernet for data, and a different CRC-16 to USB High Speed data for packet headers.

Super Speed is thus much more capable of detecting errors in transfer than High Speed.

A way out for a.out

Posted Apr 19, 2022 13:30 UTC (Tue) by nix (subscriber, #2304) [Link]

This was all SS, according to dmesg. Major corruption nonetheless :/

A way out for a.out

Posted Apr 12, 2022 10:27 UTC (Tue) by james (subscriber, #1325) [Link]

Docking stations tend to be USB-C or Thunderbird these days (looks like Dell don't sell anything else), so naturally the NICs are USB 3. As far as I know, Surface Pro docking stations (with a custom connector) have USB NICs inside, too.

I would argue that this means laptop manufacturers are sufficiently happy with USB NICs to risk having them on the desks of millions of decision-makers, if it wasn't for my experience with a dodgy Surface Pro 3 and dock, where a jolt to the desk would temporarily disconnect the USB connection and drop all SSH sessions. I replaced that with a USB NIC and was much happier (until I persuaded work to give me a proper laptop instead).

A way out for a.out

Posted Mar 26, 2022 0:36 UTC (Sat) by mss (subscriber, #138799) [Link] (1 responses)

Waiting for this PC-Engines ALIX to die but it doesn't want to.
I still remember working with ALIX predecessor board from PC-Engines - WRAP.
Still had NSC logo on the chip.
Alix was fun platform. That Geode LX cpu which was either 586 or 686 depending who asked.
If my memory serves me right I remember Geode being treated as a 686 in the userspace as it supported the CMOV series of x86 instructions, which was apparently the defining difference between a 586 and a 686 (at least from the userspace perspective).

A way out for a.out

Posted Mar 26, 2022 5:01 UTC (Sat) by wtarreau (subscriber, #51152) [Link]

> If my memory serves me right I remember Geode being treated as a 686 in the userspace as it supported the CMOV series of x86 instructions, which was apparently the defining difference between a 586 and a 686 (at least from the userspace perspective).

It was a bit more complicated in fact. It would only implement CMOV between registers and not from memory. However, compilers would almost never emit CMOV from memory, so generally speaking that was OK to build with -march=i686. Once in a while you'd find a faulty program though, that needed to be rebuilt for i586. What a painful period! And there was a real benefit in trying to use CMOV by then since branch predictors were still non-existent.

A way out for a.out

Posted Mar 24, 2022 17:05 UTC (Thu) by glaubitz (subscriber, #96452) [Link] (4 responses)

Quote: "Kees Cook did do a little research on, seemingly, the only distribution that still supports Alpha (Gentoo)"

That is not correct though. Debian is also still supporting the Alpha architecture among other older architectures under the umbrella of the Debian Ports project.

See: https://cdimage.debian.org/cdimage/ports/ and: https://www.ports.debian.org/

Disclaimer: I'm one of the primary maintainers of Debian Ports.

A way out for a.out

Posted Mar 25, 2022 5:23 UTC (Fri) by rdeforest (guest, #153619) [Link] (3 responses)

Thank you for your work! I don't directly benefit from it but I appreciate the value to society. It's the kind of thing I tell people about when trying to explain the importance of the Debian project overall.

Has there really been no news in the Debian Ports world since May of 2019, or is none of the news since then worthy of the project's front page?

A way out for a.out

Posted Mar 25, 2022 5:28 UTC (Fri) by glaubitz (subscriber, #96452) [Link] (2 responses)

> Thank you for your work! I don't directly benefit from it but I appreciate the value to society. It's the kind of thing I tell people about when trying to explain the importance of the Debian project overall.

Thanks, I appreciate the praise. It's also fun to work on these old machines and we're making good progress even with getting Rust supported on m68k ;-).

> Has there really been no news in the Debian Ports world since May of 2019, or is none of the news since then worthy of the project's front page?

We don't really have an active web team for Debian Ports, most of the discussion happens on the mailing list.

As you can see from the folder with the CD images, we are more or less regularly push out new Debian unstable snapshots.

A way out for a.out

Posted Mar 25, 2022 8:21 UTC (Fri) by taladar (subscriber, #68407) [Link] (1 responses)

> most of the discussion happens on the mailing list.

Might be worth at least posting that somewhere prominently on the web page so people don't assume the project is dead.

A way out for a.out

Posted Mar 25, 2022 9:03 UTC (Fri) by beagnach (guest, #32987) [Link]

Agreed - something as simple as a small feed showing the most active email conversations recently, and the most recent releases would make a massive difference - the web page, which is the most likely first port of call for anyone with a casual interest, makes it look like the project is moribund.

A way out for a.out

Posted Mar 24, 2022 17:20 UTC (Thu) by pebolle (guest, #35204) [Link] (3 responses)

> an ELF wrapper program that could load and run old a.out binaries

Nitpick: that's not a wrapper but a loader, isn't it?

Anyhow, would it be possible to write an a.out to ELF converter? Ie, a program that is fed an a.out executable and creates an ELF executable (basically this loader and the a.out dumped into an ELF executable).

A way out for a.out

Posted Mar 24, 2022 20:21 UTC (Thu) by gutschke (subscriber, #27910) [Link] (2 responses)

A.out is an insanely simple file format, and basic ELF isn't really all that complex either. So, I would expect that there'd be some way to convert a.out to ELF without too much effort. In particular, it appears as if the only binaries anybody cares about are statically linked already. That should dramatically simply things.

I haven't looked too closely. But there might be some need to add a bit of assembly "glue". Shouldn't be much, but that would be architecture-specific. Maybe, that's why a wrapper turned out to be easier to code.

The only other remaining issue is the fact that a.out wants to be loaded to an address that is very low. In fact, it's so low that it is usually not allowed to be mapped from user space. So, you'd quite possibly end up with ELF binaries that fail to start until you reconfigure your system, and you won't get any informative error messages. The wrapper addresses that problem a little nicer and prompts you what to do.

If I think hard enough, I can imagine solutions for all these problems. But they get increasingly more complex, for something that really doesn't justify this amount of engineering effort. If the wrapper works, that's likely the most expedient and pragmatic solution.

A way out for a.out

Posted Mar 24, 2022 23:48 UTC (Thu) by Trou.fr (subscriber, #26289) [Link]

Actually, binutils can "convert" (some) a.out programs into ELF files using objcopy. Whether they work or not is another question :)

A way out for a.out

Posted Apr 1, 2022 8:27 UTC (Fri) by anton (subscriber, #25547) [Link]

In particular, it appears as if the only binaries anybody cares about are statically linked already.
Those a.out binaries I care about are dynamically linked (pretty much everything was at the time). However, Linux broke these user space programs with the 5.1 release (so much for "we don't break user space").
Maybe, that's why a wrapper turned out to be easier to code.
Which wrapper turned out to be easier to code? The only wrapper I am aware of, Siegfried Pammer's run-aout turned out to be a lot more work and less capable than I expected. You can read all about it in his thesis, but among the difficulties was that run-aout has to emulate the uselib() system call (because the libraries are also a.out binaries). Pammer deserves high praise for tackling all these obstacles. My conclusion from all of this is that it would probably have been easier to put an a.out loader into kernel space, as an out-of-tree module if the kernel maintainers insist on eradicating a.out support from the official tree.
The only other remaining issue is the fact that a.out wants to be loaded to an address that is very low. In fact, it's so low that it is usually not allowed to be mapped from user space. So, you'd quite possibly end up with ELF binaries that fail to start until you reconfigure your system, and you won't get any informative error messages.
Yes, some of the a.out binaries have so low starting addresses that they either required starting it as root (apparently whatever makes mmap fail does not apply to root) or first setting
sudo sysctl -w vm.mmap_min_addr="4096"
However, there are also a.out binaries that still worked with the default mmap_min_addr (of IIRC kernel 4.15).

A way out for a.out

Posted Mar 24, 2022 17:51 UTC (Thu) by halla (subscriber, #14185) [Link]

"There was a time when the crazier people among us manually converted our Slackware systems from a.out to ELF in order to be able to try it out and gain the benefits before distributions were updated."

I remember trying that...

A way out for a.out

Posted Mar 24, 2022 20:29 UTC (Thu) by cuviper (subscriber, #56273) [Link] (3 responses)

Now, will GCC ever change the default executable name from "a.out"?

A way out for a.out

Posted Mar 24, 2022 21:49 UTC (Thu) by JoeBuck (subscriber, #2330) [Link] (2 responses)

a.out goes back to the original Unix, and apparently came from "assembler output", even though it is really linker output. So the name is at least 40 years old. Changing it at this point is probably not worth the bother, since there's probably something that depends on that.

A way out for a.out

Posted Mar 24, 2022 22:36 UTC (Thu) by gerdesj (subscriber, #5446) [Link] (1 responses)

"Changing it at this point is probably not worth the bother, since there's probably something that depends on that."

A shitload of documentation. lol here's some C, wack it into a file called x.c, run this (gcc command) and then run ./a.out.

A way out for a.out

Posted Mar 27, 2022 17:10 UTC (Sun) by NYKevin (subscriber, #129325) [Link]

I imagine there are some students who honestly believe that ./a.out is "just a funny-looking command" and not, y'know, a file name.

A way out for a.out

Posted Mar 25, 2022 5:57 UTC (Fri) by bsdimp (guest, #18082) [Link]

I wrote s Venix/86 emulaor. It runs the 16 bit a.out binaries by loading them into memory, setting up the registers and using vm86 to jump to the 16bit code. I've been able to run all the venix binaries this way.

The code posted assumes the a.out system call ABI is the same as the ELF one. This wasn't true for my venix emulaor so i had to interpret the system calls. It was easy for 16bit code runnimg in a 32bit binary, but would be harder for 32bit code. Otherwise it is quite similar to what I wrote.

You can find my FOSDEM 2022 presentation here https://fosdem.org/2022/schedule/event/venix/

Sooo close!

Posted Mar 25, 2022 6:45 UTC (Fri) by felixfix (subscriber, #242) [Link] (1 responses)

I was soooo hoping for the full "one never knows, do one?" from "Your Feet's Too Big" by Fats Waller, https://www.youtube.com/watch?v=nG3rgcU6CqI (way at the end).

I'd apologize for the off-topic reference, but one can never have too many Fats Waller links, can one?

Sooo close!

Posted Mar 28, 2022 15:39 UTC (Mon) by rsidd (subscriber, #2582) [Link]

I see hardly any Fats Waller links, so one is not too many, thanks!

A way out for a.out

Posted Mar 27, 2022 17:34 UTC (Sun) by jdulaney (subscriber, #83672) [Link] (1 responses)

Be cool if GCC was set to do elf by default for all those hello worlds.

A way out for a.out

Posted Mar 30, 2022 9:32 UTC (Wed) by immibis (subscriber, #105511) [Link]

??? it does. The file is called a.out by default but the file format is ELF

A way out for a.out

Posted Apr 6, 2022 18:24 UTC (Wed) by anton (subscriber, #25547) [Link]

I have now tried Kees Cook's aout program:
./aout /usr/local/bin/gforth-0.3.0
/lib/ld.so: cache '/etc/ld.so.cache' is corrupt
/usr/local/bin/gforth-0.3.0: can't load library '/usr/lib/libm.so.4'
        Exec format error
/usr/local/bin/gforth-0.3.0: can't find library 'libm.so.4'
It's interesting that the old dynamic linker can no longer handle Debian 11 ld.so.cache (still worked on Debian 8), but putting a link in /usr/lib got around that problem. But then of course uselib cannot deal with the format of libm.so.4.6.27, which is a.out.

If anybody wants to do their own experiments, here are some a.out binaries and libraries. Not all of them worked on Debian 8, but at least gforth-0.3.0 did as root or if I used

sudo sysctl -w vm.mmap_min_addr="4096"
I also tried the suggested alternative of rebuilding gforth-0.3.0. Some of the early hurdles were relatively easy to overcome, but eventually I had a binary to run, and it crashed; my guess is that the reason is that modern libcs no longer use RWX permissions for malloc()ed memory. Fixing this would be a somewhat more involved, and it may be getting away from my purpose of running the old program: to be able to compare its behaviour to that of modern programs (e.g., recent versions of gforth).


Copyright © 2022, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds