Dr. Brian Robert Callahan
academic, developer, with an eye towards a brighter techno-social life
As soon as I finished writing up the previous blog post, I was made aware of the announcement of a new programming language named Hare. It was pointed out to me that Hare released with Linux and FreeBSD support. We'll just have to port it to OpenBSD. Let's get to work.
Hare comes in two repositories: a compiler and a runtime. This blog post will only deal with porting the compiler; we'll port the runtime in a follow-up post.
First I cloned the compiler and copied the rt/+freebsd
directory to a new rt/+openbsd
directory and did the rote renaming from FreeBSD to OpenBSD in the new directory. Next, I had to modify rt/+openbsd/errno.ha
to reflect the reality in OpenBSD. The file to look at is here and it really is just a rote making the changes to match. Then I had to do the same thing for rt/+openbsd/syscallno.ha
which is just again a rote making the changes from here. I then edited rt/configure
to copy the FreeBSD section into an OpenBSD section and make the rote changes inside the new OpenBSD section.
Now I could begin building the Hare compiler. The instructions said to create a new build directory and from there run ../configure
so that's what I did. Hare uses QBE for its backend. Good thing I recently imported a QBE port.
Hare is not a particularly big compiler so there are only a handful of files to build. I did run into some build errors though: the Hare compiler uses a mktemp
function that does not match the mktemp(3) prototype. So that caused an error. The fix is simple—all you have to do is rename all the occurances of mktemp
in the Hare code. I renamed it to emktemp
since I'm not yet worried about selecting the final new name right now.
I then had several occurances of printf
format string warnings but because -Werror
was turned on from upstream, these broke the build. Fortunately, clang will tell you what you need to change the offending format strings to, so I just listened to clang. I think that OpenBSD differs from Linux and FreeBSD here (think: the difference between %ld
and %lld
), but it is all legal according to the C spec, so this might be something upstream will need to smooth over.
And hey the build finished. The instructions say you can run make check
to run the test suite. So I did that.
And all the tests failed.
OpenBSD has some special requirements for its ELF binaries. All OpenBSD binaries need a .note.openbsd.ident
section with a couple of magic numbers and the string "OpenBSD"
. I may be misremembering, but I believe that this is an artifact of when OpenBSD had Linux emulation so the kernel would know if an ELF binary was a Linux or OpenBSD binary. The Linux emulation was removed but the special identifier stayed. We actually saw the special code needed for this all the way back in our SnakeQR game. I added this code into the assembly code for the _start
function.
I then needed to teach the Hare linker script to recognize and keep the new .note.openbsd.ident
section.
Now I can rebuild and retest.
And the tests still failed.
Opening a test binary with GDB and forcing the debugger to break at the very first instruction with starti
, I noticed that the memory location for the first instruction kept changing each time I reran the program. Looks like I forgot to tell the linker that it needs to include the -nopie
flag.
Another quick rebuild and retest and all the tests passed.
I sent a patch with all these changes to the mailing list. It won't go in as-is, due to the printf
format string mismatches between OpenBSD and the others, and maybe a few other tweaks.
This was a very quick and simple porting job. But there is always something to learn. Now that the compiler is finished, I'll work on the standard library and then work on riscv64 and arm64 support. Stay tuned!