Eventually, I’d like to write shared libraries in go, in particular I want my go code callable from the android dalvik virtual machine. So, after a long and intense staring contest with the tools and the go runtime, I have a proof of concept running under linux/x64. I know that your contribution guide mentions that I should write my design before coding, but in this case I chose to do the experiments myself first to get a feel of the go code and to figure out if it was even possible for me to implement.
With the two CLs applied, building the runtime with PIC support is done with
after which you can run the attached test case like this:
./build.sh && LD_LIBRARY_PATH=. ./main
which should give the following output:
Main, calling cgo
From test, calling go
C main, calling Go_callback
C main exiting
The test case demonstrates a C main program loading a go shared library (libgo.so), which in turn loads a C shared library (libtest.so). The test case calling sequence is as follows:
1. libgo.so DT_INIT is run by the dynamic linker. Go is initialized and main.main() is run. In this case, libtest.so is called from main.main through cgo.
2. main.main() returns and instead of exiting, control is relinquished back to the dynamic linker which in turn calls the C main().
3. C main() calls back into libgo.so through cgo and exits.
The tool changes (http://codereview.appspot.com/6775101) adds the new “-lib” flag to the go tool and the -U flags to 6l, 6g and 6c. With -U the 6g and 6c tools outputs code compatible with position independent code. 6l in turn outputs the necessary relocations and uses RIP-relative addressing in the resulting machine code. It also sets up DT_INIT to initialize the library and it marks the resulting elf file as a shared library instead of a regular executable. The resulting file is an elf shared library (ET_DYN) and can be used both as a executable and as a shared library. When run as an executable, there is the added benefit of activating ASLR since the file is recognized as position independent.
The runtime changes (http://codereview.appspot.com/6822078) adds runtime support for go shared libraries. In particular:
1. Assembler changes to allow 6l to output RIP-relative addressing on x64.
2. Scheduler changes to allow the main go routine to exit cleanly and relinquish control back to the main program (proc.c).
3. Changes to the stack unwinding code to compensate for the runtime relocations (symtab.c).
4. Changes the VDSO loader to use /proc/maps instead of the ancillary vector which is not available from the library init (vdso_linux_amd64.c and runtime.c)
I don’t expect the changes to go in as is, but I would very much welcome reviews, comments etc., to allow for go shared library support, eventually on the other platforms and archs too.