]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd: reference symbols by name when linking against Go shared library
authorCherry Zhang <cherryyz@google.com>
Thu, 17 Oct 2019 01:42:18 +0000 (21:42 -0400)
committerCherry Zhang <cherryyz@google.com>
Mon, 21 Oct 2019 21:57:01 +0000 (21:57 +0000)
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 <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/compile/internal/gc/main.go
src/cmd/go/alldocs.go
src/cmd/go/internal/work/build.go
src/cmd/go/internal/work/init.go
src/cmd/internal/obj/link.go
src/cmd/internal/obj/sym.go

index c21d939b4ccfc7c9ada296edd5bb371ffd43eebb..121342e80d948d7d7a9e88931f2d46bc04f79560 100644 (file)
@@ -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`")
index 2561f5b2f8d6379a30e3c35f02e6b2167e170cfd..4774ee8201e0f6287e38e12b2fc0ac86bfdef0de 100644 (file)
 //     -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.
index 54b049b68fe0db94cc9d955d65e78e020fad05ae..6264593c34596e36af81fb9afbe0fc843c07ebbe 100644 (file)
@@ -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.
index f3055b62937b539e1921e8245eb80e3eff860e24..f4ae0e11c1c1331d7c25e0df8c943290ffcd1eb4 100644 (file)
@@ -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")
                }
index 2c106bab30d9a73ef5b4b2d843a7291b3a052cc0..2e94d5522529cfbf3bc24c3d805c3d1ea72f6660 100644 (file)
@@ -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
index de415695f333ec47a910ea47131853fc98eb328b..4c116d28f2b8cc6157585d6c31f3b828ba7a5c60 100644 (file)
@@ -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)) {