github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/cmd/link/internal/ld/symtab.go (about)

     1  // Inferno utils/6l/span.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package ld
    32  
    33  import (
    34  	"cmd/internal/obj"
    35  	"cmd/internal/sys"
    36  	"fmt"
    37  	"path/filepath"
    38  	"strings"
    39  )
    40  
    41  // Symbol table.
    42  
    43  func putelfstr(s string) int {
    44  	if len(Elfstrdat) == 0 && s != "" {
    45  		// first entry must be empty string
    46  		putelfstr("")
    47  	}
    48  
    49  	// When dynamically linking, we create LSym's by reading the names from
    50  	// the symbol tables of the shared libraries and so the names need to
    51  	// match exactly. Tools like DTrace will have to wait for now.
    52  	if !DynlinkingGo() {
    53  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
    54  		s = strings.Replace(s, "·", ".", -1)
    55  	}
    56  
    57  	off := len(Elfstrdat)
    58  	Elfstrdat = append(Elfstrdat, s...)
    59  	Elfstrdat = append(Elfstrdat, 0)
    60  	return off
    61  }
    62  
    63  func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
    64  	if elf64 {
    65  		Thearch.Lput(uint32(off))
    66  		Cput(uint8(info))
    67  		Cput(uint8(other))
    68  		Thearch.Wput(uint16(shndx))
    69  		Thearch.Vput(uint64(addr))
    70  		Thearch.Vput(uint64(size))
    71  		Symsize += ELF64SYMSIZE
    72  	} else {
    73  		Thearch.Lput(uint32(off))
    74  		Thearch.Lput(uint32(addr))
    75  		Thearch.Lput(uint32(size))
    76  		Cput(uint8(info))
    77  		Cput(uint8(other))
    78  		Thearch.Wput(uint16(shndx))
    79  		Symsize += ELF32SYMSIZE
    80  	}
    81  }
    82  
    83  var numelfsym int = 1 // 0 is reserved
    84  
    85  var elfbind int
    86  
    87  func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
    88  	var type_ int
    89  
    90  	switch t {
    91  	default:
    92  		return
    93  
    94  	case 'T':
    95  		type_ = STT_FUNC
    96  
    97  	case 'D':
    98  		type_ = STT_OBJECT
    99  
   100  	case 'B':
   101  		type_ = STT_OBJECT
   102  
   103  	case 'U':
   104  		// ElfType is only set for symbols read from Go shared libraries, but
   105  		// for other symbols it is left as STT_NOTYPE which is fine.
   106  		type_ = int(x.ElfType)
   107  
   108  	case 't':
   109  		type_ = STT_TLS
   110  	}
   111  
   112  	xo := x
   113  	for xo.Outer != nil {
   114  		xo = xo.Outer
   115  	}
   116  
   117  	var elfshnum int
   118  	if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ {
   119  		elfshnum = SHN_UNDEF
   120  	} else {
   121  		if xo.Sect == nil {
   122  			Ctxt.Cursym = x
   123  			Diag("missing section in putelfsym")
   124  			return
   125  		}
   126  		if xo.Sect.Elfsect == nil {
   127  			Ctxt.Cursym = x
   128  			Diag("missing ELF section in putelfsym")
   129  			return
   130  		}
   131  		elfshnum = xo.Sect.Elfsect.shnum
   132  	}
   133  
   134  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   135  	// maybe one day STB_WEAK.
   136  	bind := STB_GLOBAL
   137  
   138  	if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Attr.Local() {
   139  		bind = STB_LOCAL
   140  	}
   141  
   142  	// In external linking mode, we have to invoke gcc with -rdynamic
   143  	// to get the exported symbols put into the dynamic symbol table.
   144  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   145  	// mark all Go symbols local (not global) in the final executable.
   146  	// But when we're dynamically linking, we need all those global symbols.
   147  	if !DynlinkingGo() && Linkmode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF {
   148  		bind = STB_LOCAL
   149  	}
   150  
   151  	if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
   152  		addr -= int64(xo.Sect.Vaddr)
   153  	}
   154  	other := STV_DEFAULT
   155  	if x.Type&obj.SHIDDEN != 0 {
   156  		other = STV_HIDDEN
   157  	}
   158  	if (Buildmode == BuildmodePIE || DynlinkingGo()) && SysArch.Family == sys.PPC64 && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
   159  		// On ppc64 the top three bits of the st_other field indicate how
   160  		// many instructions separate the global and local entry points. In
   161  		// our case it is two instructions, indicated by the value 3.
   162  		other |= 3 << 5
   163  	}
   164  
   165  	if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT {
   166  		// When dynamically linking, we want references to functions defined
   167  		// in this module to always be to the function object, not to the
   168  		// PLT. We force this by writing an additional local symbol for every
   169  		// global function symbol and making all relocations against the
   170  		// global symbol refer to this local symbol instead (see
   171  		// (*LSym).ElfsymForReloc). This is approximately equivalent to the
   172  		// ELF linker -Bsymbolic-functions option, but that is buggy on
   173  		// several platforms.
   174  		putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other)
   175  		x.LocalElfsym = int32(numelfsym)
   176  		numelfsym++
   177  		return
   178  	} else if bind != elfbind {
   179  		return
   180  	}
   181  
   182  	putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
   183  	x.Elfsym = int32(numelfsym)
   184  	numelfsym++
   185  }
   186  
   187  func putelfsectionsym(s *LSym, shndx int) {
   188  	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
   189  	s.Elfsym = int32(numelfsym)
   190  	numelfsym++
   191  }
   192  
   193  func Asmelfsym() {
   194  	// the first symbol entry is reserved
   195  	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
   196  
   197  	dwarfaddelfsectionsyms()
   198  
   199  	// Some linkers will add a FILE sym if one is not present.
   200  	// Avoid having the working directory inserted into the symbol table.
   201  	// It is added with a name to avoid problems with external linking
   202  	// encountered on some versions of Solaris. See issue #14957.
   203  	putelfsyment(putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
   204  	numelfsym++
   205  
   206  	elfbind = STB_LOCAL
   207  	genasmsym(putelfsym)
   208  
   209  	elfbind = STB_GLOBAL
   210  	elfglobalsymndx = numelfsym
   211  	genasmsym(putelfsym)
   212  }
   213  
   214  func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
   215  	switch t {
   216  	case 'T', 'L', 'D', 'B':
   217  		if ver != 0 {
   218  			t += 'a' - 'A'
   219  		}
   220  		fallthrough
   221  
   222  	case 'a',
   223  		'p',
   224  		'f',
   225  		'z',
   226  		'Z',
   227  		'm':
   228  		l := 4
   229  		if HEADTYPE == obj.Hplan9 && SysArch.Family == sys.AMD64 && Debug['8'] == 0 {
   230  			Lputb(uint32(addr >> 32))
   231  			l = 8
   232  		}
   233  
   234  		Lputb(uint32(addr))
   235  		Cput(uint8(t + 0x80)) /* 0x80 is variable length */
   236  
   237  		var i int
   238  		if t == 'z' || t == 'Z' {
   239  			Cput(s[0])
   240  			for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 {
   241  				Cput(s[i])
   242  				Cput(s[i+1])
   243  			}
   244  
   245  			Cput(0)
   246  			Cput(0)
   247  			i++
   248  		} else {
   249  			/* skip the '<' in filenames */
   250  			if t == 'f' {
   251  				s = s[1:]
   252  			}
   253  			for i = 0; i < len(s); i++ {
   254  				Cput(s[i])
   255  			}
   256  			Cput(0)
   257  		}
   258  
   259  		Symsize += int32(l) + 1 + int32(i) + 1
   260  
   261  	default:
   262  		return
   263  	}
   264  }
   265  
   266  func Asmplan9sym() {
   267  	genasmsym(putplan9sym)
   268  }
   269  
   270  var symt *LSym
   271  
   272  func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) }
   273  func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) }
   274  func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) }
   275  
   276  func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) }
   277  func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) }
   278  func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) }
   279  
   280  func Append16b(b []byte, v uint16) []byte {
   281  	return append(b, uint8(v>>8), uint8(v))
   282  }
   283  func Append16l(b []byte, v uint16) []byte {
   284  	return append(b, uint8(v), uint8(v>>8))
   285  }
   286  
   287  func Append32b(b []byte, v uint32) []byte {
   288  	return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
   289  }
   290  func Append32l(b []byte, v uint32) []byte {
   291  	return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24))
   292  }
   293  
   294  func Append64b(b []byte, v uint64) []byte {
   295  	return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32),
   296  		uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
   297  }
   298  
   299  func Append64l(b []byte, v uint64) []byte {
   300  	return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24),
   301  		uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56))
   302  }
   303  
   304  type byPkg []*Library
   305  
   306  func (libs byPkg) Len() int {
   307  	return len(libs)
   308  }
   309  
   310  func (libs byPkg) Less(a, b int) bool {
   311  	return libs[a].Pkg < libs[b].Pkg
   312  }
   313  
   314  func (libs byPkg) Swap(a, b int) {
   315  	libs[a], libs[b] = libs[b], libs[a]
   316  }
   317  
   318  func symtab() {
   319  	dosymtype()
   320  
   321  	// Define these so that they'll get put into the symbol table.
   322  	// data.c:/^address will provide the actual values.
   323  	xdefine("runtime.text", obj.STEXT, 0)
   324  
   325  	xdefine("runtime.etext", obj.STEXT, 0)
   326  	xdefine("runtime.typelink", obj.SRODATA, 0)
   327  	xdefine("runtime.etypelink", obj.SRODATA, 0)
   328  	xdefine("runtime.itablink", obj.SRODATA, 0)
   329  	xdefine("runtime.eitablink", obj.SRODATA, 0)
   330  	xdefine("runtime.rodata", obj.SRODATA, 0)
   331  	xdefine("runtime.erodata", obj.SRODATA, 0)
   332  	xdefine("runtime.types", obj.SRODATA, 0)
   333  	xdefine("runtime.etypes", obj.SRODATA, 0)
   334  	xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
   335  	xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
   336  	xdefine("runtime.data", obj.SDATA, 0)
   337  	xdefine("runtime.edata", obj.SDATA, 0)
   338  	xdefine("runtime.bss", obj.SBSS, 0)
   339  	xdefine("runtime.ebss", obj.SBSS, 0)
   340  	xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0)
   341  	xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0)
   342  	xdefine("runtime.end", obj.SBSS, 0)
   343  	xdefine("runtime.epclntab", obj.SRODATA, 0)
   344  	xdefine("runtime.esymtab", obj.SRODATA, 0)
   345  
   346  	// garbage collection symbols
   347  	s := Linklookup(Ctxt, "runtime.gcdata", 0)
   348  
   349  	s.Type = obj.SRODATA
   350  	s.Size = 0
   351  	s.Attr |= AttrReachable
   352  	xdefine("runtime.egcdata", obj.SRODATA, 0)
   353  
   354  	s = Linklookup(Ctxt, "runtime.gcbss", 0)
   355  	s.Type = obj.SRODATA
   356  	s.Size = 0
   357  	s.Attr |= AttrReachable
   358  	xdefine("runtime.egcbss", obj.SRODATA, 0)
   359  
   360  	// pseudo-symbols to mark locations of type, string, and go string data.
   361  	var symtype *LSym
   362  	var symtyperel *LSym
   363  	if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
   364  		s = Linklookup(Ctxt, "type.*", 0)
   365  
   366  		s.Type = obj.STYPE
   367  		s.Size = 0
   368  		s.Attr |= AttrReachable
   369  		symtype = s
   370  
   371  		s = Linklookup(Ctxt, "typerel.*", 0)
   372  
   373  		s.Type = obj.STYPERELRO
   374  		s.Size = 0
   375  		s.Attr |= AttrReachable
   376  		symtyperel = s
   377  	} else if !DynlinkingGo() {
   378  		s = Linklookup(Ctxt, "type.*", 0)
   379  
   380  		s.Type = obj.STYPE
   381  		s.Size = 0
   382  		s.Attr |= AttrReachable
   383  		symtype = s
   384  		symtyperel = s
   385  	}
   386  
   387  	groupSym := func(name string, t int16) *LSym {
   388  		s := Linklookup(Ctxt, name, 0)
   389  		s.Type = t
   390  		s.Size = 0
   391  		s.Attr |= AttrLocal | AttrReachable
   392  		return s
   393  	}
   394  	var (
   395  		symgostring    = groupSym("go.string.*", obj.SGOSTRING)
   396  		symgostringhdr = groupSym("go.string.hdr.*", obj.SGOSTRINGHDR)
   397  		symgofunc      = groupSym("go.func.*", obj.SGOFUNC)
   398  		symgcbits      = groupSym("runtime.gcbits.*", obj.SGCBITS)
   399  	)
   400  
   401  	symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
   402  	symtypelink.Type = obj.STYPELINK
   403  
   404  	symitablink := Linklookup(Ctxt, "runtime.itablink", 0)
   405  	symitablink.Type = obj.SITABLINK
   406  
   407  	symt = Linklookup(Ctxt, "runtime.symtab", 0)
   408  	symt.Attr |= AttrLocal
   409  	symt.Type = obj.SSYMTAB
   410  	symt.Size = 0
   411  	symt.Attr |= AttrReachable
   412  
   413  	ntypelinks := 0
   414  	nitablinks := 0
   415  
   416  	// assign specific types so that they sort together.
   417  	// within a type they sort by size, so the .* symbols
   418  	// just defined above will be first.
   419  	// hide the specific symbols.
   420  	for _, s := range Ctxt.Allsym {
   421  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != obj.SRODATA {
   422  			continue
   423  		}
   424  
   425  		switch {
   426  		case strings.HasPrefix(s.Name, "type."):
   427  			if !DynlinkingGo() {
   428  				s.Attr |= AttrHidden
   429  			}
   430  			if UseRelro() {
   431  				s.Type = obj.STYPERELRO
   432  				s.Outer = symtyperel
   433  			} else {
   434  				s.Type = obj.STYPE
   435  				s.Outer = symtype
   436  			}
   437  
   438  		case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro():
   439  			// Keep go.importpath symbols in the same section as types and
   440  			// names, as they can be referred to by a section offset.
   441  			s.Type = obj.STYPERELRO
   442  
   443  		case strings.HasPrefix(s.Name, "go.typelink."):
   444  			ntypelinks++
   445  			s.Type = obj.STYPELINK
   446  			s.Attr |= AttrHidden
   447  			s.Outer = symtypelink
   448  
   449  		case strings.HasPrefix(s.Name, "go.itablink."):
   450  			nitablinks++
   451  			s.Type = obj.SITABLINK
   452  			s.Attr |= AttrHidden
   453  			s.Outer = symitablink
   454  
   455  		case strings.HasPrefix(s.Name, "go.string."):
   456  			s.Type = obj.SGOSTRING
   457  			s.Attr |= AttrHidden
   458  			s.Outer = symgostring
   459  			if strings.HasPrefix(s.Name, "go.string.hdr.") {
   460  				s.Type = obj.SGOSTRINGHDR
   461  				s.Outer = symgostringhdr
   462  			}
   463  
   464  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   465  			s.Type = obj.SGCBITS
   466  			s.Attr |= AttrHidden
   467  			s.Outer = symgcbits
   468  
   469  		case strings.HasPrefix(s.Name, "go.func."):
   470  			s.Type = obj.SGOFUNC
   471  			s.Attr |= AttrHidden
   472  			s.Outer = symgofunc
   473  
   474  		case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"):
   475  			s.Type = obj.SGOFUNC
   476  			s.Attr |= AttrHidden
   477  			s.Outer = symgofunc
   478  			s.Align = 4
   479  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   480  		}
   481  	}
   482  
   483  	if Buildmode == BuildmodeShared {
   484  		abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0)
   485  		abihashgostr.Attr |= AttrReachable
   486  		abihashgostr.Type = obj.SRODATA
   487  		hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0)
   488  		Addaddr(Ctxt, abihashgostr, hashsym)
   489  		adduint(Ctxt, abihashgostr, uint64(hashsym.Size))
   490  	}
   491  
   492  	// Information about the layout of the executable image for the
   493  	// runtime to use. Any changes here must be matched by changes to
   494  	// the definition of moduledata in runtime/symtab.go.
   495  	// This code uses several global variables that are set by pcln.go:pclntab.
   496  	moduledata := Ctxt.Moduledata
   497  	// The pclntab slice
   498  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
   499  	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
   500  	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
   501  	// The ftab slice
   502  	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset))
   503  	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
   504  	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
   505  	// The filetab slice
   506  	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
   507  	adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1)
   508  	adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1)
   509  	// findfunctab
   510  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
   511  	// minpc, maxpc
   512  	Addaddr(Ctxt, moduledata, pclntabFirstFunc)
   513  	Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
   514  	// pointers to specific parts of the module
   515  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0))
   516  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0))
   517  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0))
   518  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0))
   519  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0))
   520  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0))
   521  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0))
   522  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0))
   523  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0))
   524  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0))
   525  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0))
   526  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0))
   527  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0))
   528  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.types", 0))
   529  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypes", 0))
   530  	// The typelinks slice
   531  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
   532  	adduint(Ctxt, moduledata, uint64(ntypelinks))
   533  	adduint(Ctxt, moduledata, uint64(ntypelinks))
   534  	// The itablinks slice
   535  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.itablink", 0))
   536  	adduint(Ctxt, moduledata, uint64(nitablinks))
   537  	adduint(Ctxt, moduledata, uint64(nitablinks))
   538  	if len(Ctxt.Shlibs) > 0 {
   539  		thismodulename := filepath.Base(outfile)
   540  		switch Buildmode {
   541  		case BuildmodeExe, BuildmodePIE:
   542  			// When linking an executable, outfile is just "a.out". Make
   543  			// it something slightly more comprehensible.
   544  			thismodulename = "the executable"
   545  		}
   546  		addgostring(moduledata, "go.link.thismodulename", thismodulename)
   547  
   548  		modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0)
   549  		modulehashes.Attr |= AttrReachable
   550  		modulehashes.Attr |= AttrLocal
   551  		modulehashes.Type = obj.SRODATA
   552  
   553  		for i, shlib := range Ctxt.Shlibs {
   554  			// modulehashes[i].modulename
   555  			modulename := filepath.Base(shlib.Path)
   556  			addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   557  
   558  			// modulehashes[i].linktimehash
   559  			addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   560  
   561  			// modulehashes[i].runtimehash
   562  			abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0)
   563  			abihash.Attr |= AttrReachable
   564  			Addaddr(Ctxt, modulehashes, abihash)
   565  		}
   566  
   567  		Addaddr(Ctxt, moduledata, modulehashes)
   568  		adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
   569  		adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
   570  	}
   571  
   572  	// The rest of moduledata is zero initialized.
   573  	// When linking an object that does not contain the runtime we are
   574  	// creating the moduledata from scratch and it does not have a
   575  	// compiler-provided size, so read it from the type data.
   576  	moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0)
   577  	moduledata.Size = decodetype_size(moduledatatype)
   578  	Symgrow(Ctxt, moduledata, moduledata.Size)
   579  
   580  	lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0)
   581  	if lastmoduledatap.Type != obj.SDYNIMPORT {
   582  		lastmoduledatap.Type = obj.SNOPTRDATA
   583  		lastmoduledatap.Size = 0 // overwrite existing value
   584  		Addaddr(Ctxt, lastmoduledatap, moduledata)
   585  	}
   586  }