From: Cherry Zhang Date: Thu, 17 Oct 2019 01:42:18 +0000 (-0400) Subject: [dev.link] cmd: reference symbols by name when linking against Go shared library X-Git-Tag: go1.14beta1~292^2^2~34 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=97e497b2537d0d9588e52bb0c20df59604e6f098;p=gostls13.git [dev.link] cmd: reference symbols by name when linking against Go shared library When building a program that links against Go shared libraries, it needs to reference symbols defined in the shared library. At compile time, we don't know where the shared library boundary is. If we reference a symbol in package p by index, and package p is actually part of a shared library, we cannot resolve the index at link time, as the linker doesn't see the object file of p. So when linking against Go shared libraries, always use named reference for now. To do this, the compiler needs to know whether we will be linking against Go shared libraries. The -dynlink flag kind of indicates that (as the document says), but currently it is actually overloaded: it is also used when building a plugin or a shared library, which is self-contained (if -linkshared is not otherwise specified) and could use index for symbol reference. So we introduce another compiler flag, -linkshared, specifically for linking against Go shared libraries. The go command will pass this flag if its -linkshared flag is specified ("go build -linkshared"). There may be better way to handle this. For example, we can put the symbol indices in a special section in the shared library that the linker can read. Or we can generate some per-package description file to include the indices. (Currently we generate a .shlibname file for each package that is included in a shared library, which contains the path of the library. We could consider extending this.) That said, this CL is a stop-gap solution. And it is no worse than the old object files. If we were to redesign the build system so that the shared library boundary is known at compile time, we could use indices for symbol references that do not cross shared library boundary, as well as doing other things better. Change-Id: I9c02aad36518051cc4785dbe25c4b4cef8f3faeb Reviewed-on: https://go-review.googlesource.com/c/go/+/201818 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Than McIntosh --- diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index c21d939b4c..121342e80d 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -251,6 +251,7 @@ func Main(archInit func(*Arch)) { if supportsDynlink(thearch.LinkArch.Arch) { flag.BoolVar(&flag_shared, "shared", false, "generate code that can be linked into a shared library") flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries") + flag.BoolVar(&Ctxt.Flag_linkshared, "linkshared", false, "generate code that will be linked against Go shared libraries") } flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to `file`") flag.StringVar(&memprofile, "memprofile", "", "write memory profile to `file`") diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 2561f5b2f8..4774ee8201 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -145,8 +145,8 @@ // -ldflags '[pattern=]arg list' // arguments to pass on each go tool link invocation. // -linkshared -// link against shared libraries previously created with -// -buildmode=shared. +// build code that will be linked against shared libraries previously +// created with -buildmode=shared. // -mod mode // module download mode to use: readonly or vendor. // See 'go help modules' for more. diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 54b049b68f..6264593c34 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -97,8 +97,8 @@ and test commands: -ldflags '[pattern=]arg list' arguments to pass on each go tool link invocation. -linkshared - link against shared libraries previously created with - -buildmode=shared. + build code that will be linked against shared libraries previously + created with -buildmode=shared. -mod mode module download mode to use: readonly or vendor. See 'go help modules' for more. diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index f3055b6293..f4ae0e11c1 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -224,6 +224,7 @@ func buildModeInit() { base.Fatalf("-linkshared not supported on %s\n", platform) } codegenArg = "-dynlink" + forcedGcflags = append(forcedGcflags, "-linkshared") // TODO(mwhudson): remove -w when that gets fixed in linker. forcedLdflags = append(forcedLdflags, "-linkshared", "-w") } diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 2c106bab30..2e94d55225 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -648,6 +648,7 @@ type Link struct { Debugpcln string Flag_shared bool Flag_dynlink bool + Flag_linkshared bool Flag_optimize bool Flag_locationlists bool Flag_newobj bool // use new object file format diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index de415695f3..4c116d28f2 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -184,7 +184,7 @@ func (ctxt *Link) NumberSyms(asm bool) { var idx, nonpkgidx int32 = 0, 0 ctxt.traverseSyms(traverseDefs, func(s *LSym) { - if asm || s.Pkg == "_" || s.DuplicateOK() { + if asm || s.Pkg == "_" || s.DuplicateOK() || ctxt.Flag_linkshared { s.PkgIdx = goobj2.PkgIdxNone s.SymIdx = nonpkgidx if nonpkgidx != int32(len(ctxt.nonpkgdefs)) {