Dr. Brian Robert Callahan
academic, developer, with an eye towards a brighter techno-social life
Remember when I used to author blog posts on this site? Me neither. Let's fix that.
I recently noticed that the Tiny C Compiler (tcc) developers gained an interest in widening their platform support. Chief among those new platforms were the BSDs. A developer had committed most of the work necessary to almost allow tcc to compile and link working binaries on OpenBSD. I say almost, because it was missing a key final feature to make things just work(TM).
It should be stated in no uncertain terms that you use tcc at your own risk. You will lose all the mitigations you expect from in-base compilers, including but not limited to RETGUARD and ASLR. This blog post is about the process of a compiler gaining support for a new platform.
With LLVM lld and GNU ld, you can expect all modern amenities. This is not the case with the tcc linker. The last piece of the tcc puzzle was that the tcc linker did not know how to select shared libraries on OpenBSD, and as such, could only select static libraries. This meant many linker failures.
My first thought was to bypass the tcc linker entirely and pass the linking step to cc. That ended up not being ideal. If you chose to execute a full compile, tcc -o code code.c
, this would pass the entire compilation to cc. You needed to break it up into two stages, tcc -c code.c && tcc -o code code.o
, in order to actually use tcc to compile the C code. A new strategy was needed.
Fortunately, I knew how to teach the tcc linker how to select shared libraries on OpenBSD by using the same strategy I used to teach GNU gold the very same in my eternally unofficial port. I emailed the diff to the tcc developer spearheading the OpenBSD support, and it was quickly committed. Though the diff did use some OpenBSD extensions like strtonum and was eventually replaced, it was the case that tcc was able to do the right thing on OpenBSD/amd64. You could use tcc as a drop-in replacement if you wanted.
Now we had OpenBSD/amd64 support only. While tcc supports aarch64, amd64, armv7, i386, and riscv, more work was required for other platforms. This is undoubtedly due to the differences in CPUs and their ABIs. You cannot simply expect that the way things like registers are used to be consistent across all CPUs. The tcc developer I was in communication with was able to fire up a virtual machine to bring up OpenBSD/i386 support. The dveloper expressed a desire to bring up OpenBSD/arm64 and OpenBSD/armv7 support as well.
Using the virtual machine, OpenBSD/i386 support was quickly added. But that was as far as the developer could go with currently available resources. I offered the developer shell access to my BeagleBone Black and my Raspberry Pi 3B+. This quickly became two tcc developers with shell access to my machines. Development from my perspective was a matter of rebooting the machines when things crashed and little more. And quite soon, I saw a commit for OpenBSD/arm64 and OpenBSD/armv7 support. Support for OpenBSD/arm64 was completed first. The OpenBSD/armv7 support required perhaps the most significant CPU-specific changes, requiring teaching the tcc linker about more parts of ARM ELF than were needed by other platforms.
Despite not doing much more work than submitting a single diff, at this point I could go ahead and create a package that I subsequently committed. Writing the port was extremely straightfoward, which was even nicer.
And that's the story of how I donated a patch and got a free compiler in return. Sometimes donating hardware is better than donating code.