cmd/link: call moduledata symbols "local.moduledata" if they are created by the linker

This was always a bit confusing, but it also fixes a problem: runtime.firstmoduledata
was always overridden in the linker to be a local symbol but cmd/internal/obj had
already rewritten code accessing it to access it via the GOT. This works on amd64, but
causes link failures on other platforms (e.g. arm64).

Change-Id: I9b8153af74b4d0f092211d63a000d15818f39773
Reviewed-on: https://go-review.googlesource.com/13786
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 8ccbec9..f31070f 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -564,6 +564,24 @@
 	tlsg.Reachable = true
 	Ctxt.Tlsg = tlsg
 
+	moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0)
+	if moduledata.Type == 0 || moduledata.Type == obj.SDYNIMPORT {
+		// If the module we are linking does not define the
+		// runtime.firstmoduledata symbol, create a local symbol for
+		// the moduledata.
+		moduledata = Linklookup(Ctxt, "local.moduledata", 0)
+		moduledata.Local = true
+	} else {
+		// If OTOH the module does define the symbol, we truncate the
+		// symbol back to 0 bytes so we can define its entire
+		// contents.
+		moduledata.Size = 0
+	}
+	// Either way we mark it as noptrdata to hide it from the GC.
+	moduledata.Type = obj.SNOPTRDATA
+	moduledata.Reachable = true
+	Ctxt.Moduledata = moduledata
+
 	// Now that we know the link mode, trim the dynexp list.
 	x := CgoExportDynamic
 
diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go
index 33b17c5..5415434 100644
--- a/src/cmd/link/internal/ld/link.go
+++ b/src/cmd/link/internal/ld/link.go
@@ -121,31 +121,32 @@
 }
 
 type Link struct {
-	Thechar   int32
-	Thestring string
-	Goarm     int32
-	Headtype  int
-	Arch      *LinkArch
-	Debugasm  int32
-	Debugvlog int32
-	Bso       *obj.Biobuf
-	Windows   int32
-	Goroot    string
-	Hash      map[symVer]*LSym
-	Allsym    *LSym
-	Nsymbol   int32
-	Tlsg      *LSym
-	Libdir    []string
-	Library   []*Library
-	Shlibs    []Shlib
-	Tlsoffset int
-	Diag      func(string, ...interface{})
-	Cursym    *LSym
-	Version   int
-	Textp     *LSym
-	Etextp    *LSym
-	Nhistfile int32
-	Filesyms  *LSym
+	Thechar    int32
+	Thestring  string
+	Goarm      int32
+	Headtype   int
+	Arch       *LinkArch
+	Debugasm   int32
+	Debugvlog  int32
+	Bso        *obj.Biobuf
+	Windows    int32
+	Goroot     string
+	Hash       map[symVer]*LSym
+	Allsym     *LSym
+	Nsymbol    int32
+	Tlsg       *LSym
+	Libdir     []string
+	Library    []*Library
+	Shlibs     []Shlib
+	Tlsoffset  int
+	Diag       func(string, ...interface{})
+	Cursym     *LSym
+	Version    int
+	Textp      *LSym
+	Etextp     *LSym
+	Nhistfile  int32
+	Filesyms   *LSym
+	Moduledata *LSym
 }
 
 type LinkArch struct {
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 5360ec1..250c053 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -452,11 +452,7 @@
 	// runtime to use. Any changes here must be matched by changes to
 	// the definition of moduledata in runtime/symtab.go.
 	// This code uses several global variables that are set by pcln.go:pclntab.
-	moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0)
-	moduledata.Type = obj.SNOPTRDATA
-	moduledata.Size = 0 // truncate symbol back to 0 bytes to reinitialize
-	moduledata.Reachable = true
-	moduledata.Local = true
+	moduledata := Ctxt.Moduledata
 	// The pclntab slice
 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
 	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))