Get Started With Go Language on AIX
Go toolchain, the self-hosted toolchain of the new high-performance networking and multiprocessing language, is now available on AIX* 7.2 for POWER8*. This toolchain aims to complement the previous port of Go for AIX, which was made within gcc (known as the gccgo toolchain).
What Is Go Language?
Go is a new imperative language inspired by C. The current version can be found on the Go official website. It supports several OSes (including Linux* MacOS, Windows*, BSD and Solaris) and several architectures (x86, PowerPC* 64, arm, etc.). Since version 1.12, Go is also available on AIX.
Some advanced readers might be thinking, “But Go was already available with gccgo?” Yes, but Go has two toolchains: Go toolchain and gcc toolchain. Both have advantages, but gccgo supports more OSes and architectures than the Go toolchain does. For example, the Go toolchain can’t generate POWER7* assembly while gccgo can. However, the Go toolchain is much more optimized, since it has its own assembly language. Regardless, having both toolchains is an advantage.
One of the strengths of this language is also its third-party package management. Anyone can create a Go package inside its GitHub account and anyone else can retrieve and benefits from this package simply by using its git address. This open-source ecosystem allows the creation of huge software like Kubernetes or Docker, two widely recognized software offerings.
Go Compilers
As the Go toolchain is written in Go, it needs a preceding Go compiler installed on the building machine.
There are three possibilities:
- Use Go toolchain of a previous version
- Use another Go toolchain
- Cross-compile
The first possibility is the quickest and the simplest. Developers are proceeding this way when making changes inside Go itself. However, it’s not possible when attempting a first port, which was our case.
Therefore, you must fall back on the other two choices. As Go toolchain has its own compiler and linker, cross-compiling is pretty easy. However, if gccgo or GoLLVM are already available on your chosen OS, things can be easier. Being able to debug a Go binary in parallel with a gccgo binary is a huge advantage. However, Gccgo or GoLLVM must be already available on your OS, which means having ported them before.
Because most of the Go standard library is common to all toolchains, it’s a good idea to port them ahead of time. If gcc or LLVM already know about your OS or architecture, you won’t have to port any toolchain, which is the hardest part of the process.
Because the port of Go toolchain is recent, Go only works on AIX 7.2 running on POWER8 or POWER9* and for 64-bit applications. Those interested in having Go applications running on older PowerPC processors should consider gccgo. That said, 32-bit applications would need to port a whole new architecture, which the community is unlikely to be able to support.
When version 1.13 comes out around September 2019, most of the main Go features will be available inside Go toolchain, especially cgo and pprof. However, shared libraries aren’t yet available—for either Go shared library (- shared flag) or C shared library (c-shared buildmode). These modes must handle a different TOC anchor (a symbol from where all data symbols are accessed) for each library, and that’s not as easy as it seems.
This port is recent and some hidden bugs might remain. If you encounter a bug, don’t hesitate to report it to the community.
Focus on syscalls
Because Go includes its own runtime, it must provide a way to communicate with the kernel. As on C, it relies on syscalls. Most of the OSes are using assembly code like the “sc” instruction, which is calling a kernel function according to the value provided to sc. On AIX, there is no “sc” instruction, because all syscalls are instead implemented inside the libc.
For C code, a syscall is a simple jump to the corresponding libc’s function. These jumps are added by a program called by “ld” and “glink.” As Go toolchain has its own linker, “ld” isn’t called by default, therefore “glink” can’t generate these jumps. However, as we control the linker, we control the whole eXtended Common Object File Format generation and especially its loader section. Therefore, the libc symbols can be imported inside Go binaries and considered as a classical C function. As Go runtime is designed to allow the call of C functions, this can be done even to perform syscalls. Other OSes are using this process, like SunOS or MacOS since 1.12. More information can be found in the AIX runtime code.
C-Archive buildmode on AIX
C-archive buildmode allows the creation of a C static library with Go code. Due to the AIX linker, its use is slightly different from other OSes.
With Go toolchain: “-Wl,-bnoobjreorder” is mandatory because of how the Go runtime is working, see Figure 1. For those wondering why, Go toolchain and its runtime have a mechanism linked with methods based on their offset inside the .text section of the binary. This is created by Go linker before calling ld linker. If “-Wl,-bnoobjreorder” isn’t added, ld will reorder all text symbols including these methods, breaking the runtime.