Now that Go 1.21 has been released, I've returned to trying to figure out how to
dynamically link a Go program. Back in January I posted the results of my first attempt
with an earlier version of Go, which was:
1) Building a Go shared library by running
go install -buildmode=shared std
as root works fine.
2) Building a dynamically linked Go executable as a non-privileged user by adding
-linkshared
to "go build" fails with lots of file access permission errors because
the go build tool tries to write to the Go shared library, which a non-privileged
user can't do.
3) Building a dynamically link Go executable as root works but a new version
of the Go shared library gets made in the process. This makes this command
take much longer than it should. Plus, having to be root is a non-starter.
I started looking at what "go build" is doing by adding the "-x" option.
I was able to figure out how to build and link the following program
package main
func main() {
}
using a shared library. This was quite an accomplishment. But, then I tried making it into
a "Hello, world!" program.
package main
import "fmt"
func main() {
fmt.Println("Hello, world!\n")
}
This also compiles and links, but running it results in
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7fe02814e593]
goroutine 1 [running]:
os.(*File).write(...)
/usr/local/go/src/os/file_posix.go:46
os.(*File).Write(0x0, {0xc0003a6000?, 0xf, 0x7fe028059f25?})
/usr/local/go/src/os/file.go:183 +0x53
fmt.Fprintln({0x202f88, 0x0}, {0xc00035af20, 0x1, 0x1})
/usr/local/go/src/fmt/print.go:305 +0x6f
fmt.Println(...)
/usr/local/go/src/fmt/print.go:314
To compile the program I ran
WORK=/tmp/go-build3183434751
/usr/local/go/pkg/tool/linux_amd64/compile -p main -complete -installsuffix dynlink -goversion go1.21.0 -c=3 -dynlink -linkshared -nolocalimports -importcfg $WORK/b001/importcfg ./file1.go
and to link it I ran
WORK=/tmp/go-build3183434751
/usr/local/go/pkg/tool/linux_amd64/link -o a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -linkshared -w file1.o
$WORK/b001/importcfg is
packagefile fmt=/usr/local/go/pkg/linux_amd64_dynlink/fmt.a
packagefile runtime=/usr/local/go/pkg/linux_amd64_dynlink/runtime.a
packagefile runtime/cgo=/usr/local/go/pkg/linux_amd64_dynlink/runtime/cgo.a
$WORK/b001/importcfg.link is many lines like
packagefile fmt=/usr/local/go/pkg/linux_amd64_dynlink/fmt.a
packageshlib fmt=/usr/local/go/pkg/linux_amd64_dynlink/libstd.so
Both these files were created when I ran the regular "go build -linkedshare" command.
I have to admit that I don't really understand what these files should contain,
and I wouldn't be surprised if this is what's causing my problem.
Any suggestions for what I'm doing wrong?
(go version go1.21.0 linux/amd64)
Cordially,
Jon Forrest