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
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
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
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.