github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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  	"fmt"
    36  	"path/filepath"
    37  	"strings"
    38  )
    39  
    40  // Symbol table.
    41  
    42  func putelfstr(s string) int {
    43  	if len(Elfstrdat) == 0 && s != "" {
    44  		// first entry must be empty string
    45  		putelfstr("")
    46  	}
    47  
    48  	// When dynamically linking, we create LSym's by reading the names from
    49  	// the symbol tables of the shared libraries and so the names need to
    50  	// match exactly.  Tools like DTrace will have to wait for now.
    51  	if !DynlinkingGo() {
    52  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
    53  		s = strings.Replace(s, "·", ".", -1)
    54  	}
    55  
    56  	n := len(s) + 1
    57  	for len(Elfstrdat)+n > cap(Elfstrdat) {
    58  		Elfstrdat = append(Elfstrdat[:cap(Elfstrdat)], 0)[:len(Elfstrdat)]
    59  	}
    60  
    61  	off := len(Elfstrdat)
    62  	Elfstrdat = Elfstrdat[:off+n]
    63  	copy(Elfstrdat[off:], s)
    64  
    65  	return off
    66  }
    67  
    68  func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
    69  	switch Thearch.Thechar {
    70  	case '0', '6', '7', '9':
    71  		Thearch.Lput(uint32(off))
    72  		Cput(uint8(info))
    73  		Cput(uint8(other))
    74  		Thearch.Wput(uint16(shndx))
    75  		Thearch.Vput(uint64(addr))
    76  		Thearch.Vput(uint64(size))
    77  		Symsize += ELF64SYMSIZE
    78  
    79  	default:
    80  		Thearch.Lput(uint32(off))
    81  		Thearch.Lput(uint32(addr))
    82  		Thearch.Lput(uint32(size))
    83  		Cput(uint8(info))
    84  		Cput(uint8(other))
    85  		Thearch.Wput(uint16(shndx))
    86  		Symsize += ELF32SYMSIZE
    87  	}
    88  }
    89  
    90  var numelfsym int = 1 // 0 is reserved
    91  
    92  var elfbind int
    93  
    94  func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
    95  	var type_ int
    96  
    97  	switch t {
    98  	default:
    99  		return
   100  
   101  	case 'T':
   102  		type_ = STT_FUNC
   103  
   104  	case 'D':
   105  		type_ = STT_OBJECT
   106  
   107  	case 'B':
   108  		type_ = STT_OBJECT
   109  
   110  	case 'U':
   111  		// ElfType is only set for symbols read from Go shared libraries, but
   112  		// for other symbols it is left as STT_NOTYPE which is fine.
   113  		type_ = int(x.ElfType)
   114  
   115  	case 't':
   116  		type_ = STT_TLS
   117  	}
   118  
   119  	xo := x
   120  	for xo.Outer != nil {
   121  		xo = xo.Outer
   122  	}
   123  
   124  	var elfshnum int
   125  	if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ {
   126  		elfshnum = SHN_UNDEF
   127  	} else {
   128  		if xo.Sect == nil {
   129  			Ctxt.Cursym = x
   130  			Diag("missing section in putelfsym")
   131  			return
   132  		}
   133  		if xo.Sect.Elfsect == nil {
   134  			Ctxt.Cursym = x
   135  			Diag("missing ELF section in putelfsym")
   136  			return
   137  		}
   138  		elfshnum = xo.Sect.Elfsect.shnum
   139  	}
   140  
   141  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   142  	// maybe one day STB_WEAK.
   143  	bind := STB_GLOBAL
   144  
   145  	if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Local {
   146  		bind = STB_LOCAL
   147  	}
   148  
   149  	// In external linking mode, we have to invoke gcc with -rdynamic
   150  	// to get the exported symbols put into the dynamic symbol table.
   151  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   152  	// mark all Go symbols local (not global) in the final executable.
   153  	// But when we're dynamically linking, we need all those global symbols.
   154  	if !DynlinkingGo() && Linkmode == LinkExternal && x.Cgoexport&CgoExportStatic == 0 && elfshnum != SHN_UNDEF {
   155  		bind = STB_LOCAL
   156  	}
   157  
   158  	if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
   159  		addr -= int64(xo.Sect.Vaddr)
   160  	}
   161  	other := STV_DEFAULT
   162  	if x.Type&obj.SHIDDEN != 0 {
   163  		other = STV_HIDDEN
   164  	}
   165  	if (Buildmode == BuildmodePIE || DynlinkingGo()) && Thearch.Thechar == '9' && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
   166  		// On ppc64 the top three bits of the st_other field indicate how
   167  		// many instructions separate the global and local entry points. In
   168  		// our case it is two instructions, indicated by the value 3.
   169  		other |= 3 << 5
   170  	}
   171  
   172  	if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT {
   173  		// When dynamically linking, we want references to functions defined
   174  		// in this module to always be to the function object, not to the
   175  		// PLT. We force this by writing an additional local symbol for every
   176  		// global function symbol and making all relocations against the
   177  		// global symbol refer to this local symbol instead (see
   178  		// (*LSym).ElfsymForReloc). This is approximately equivalent to the
   179  		// ELF linker -Bsymbolic-functions option, but that is buggy on
   180  		// several platforms.
   181  		putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other)
   182  		x.LocalElfsym = int32(numelfsym)
   183  		numelfsym++
   184  		return
   185  	} else if bind != elfbind {
   186  		return
   187  	}
   188  
   189  	putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
   190  	x.Elfsym = int32(numelfsym)
   191  	numelfsym++
   192  }
   193  
   194  func putelfsectionsym(s *LSym, shndx int) {
   195  	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
   196  	s.Elfsym = int32(numelfsym)
   197  	numelfsym++
   198  }
   199  
   200  func putelfsymshndx(sympos int64, shndx int) {
   201  	here := Cpos()
   202  	if elf64 {
   203  		Cseek(sympos + 6)
   204  	} else {
   205  		Cseek(sympos + 14)
   206  	}
   207  
   208  	Thearch.Wput(uint16(shndx))
   209  	Cseek(here)
   210  }
   211  
   212  func Asmelfsym() {
   213  	// the first symbol entry is reserved
   214  	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
   215  
   216  	dwarfaddelfsectionsyms()
   217  
   218  	elfbind = STB_LOCAL
   219  	genasmsym(putelfsym)
   220  
   221  	elfbind = STB_GLOBAL
   222  	elfglobalsymndx = numelfsym
   223  	genasmsym(putelfsym)
   224  }
   225  
   226  func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
   227  	switch t {
   228  	case 'T', 'L', 'D', 'B':
   229  		if ver != 0 {
   230  			t += 'a' - 'A'
   231  		}
   232  		fallthrough
   233  
   234  	case 'a',
   235  		'p',
   236  		'f',
   237  		'z',
   238  		'Z',
   239  		'm':
   240  		l := 4
   241  		if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 {
   242  			Lputb(uint32(addr >> 32))
   243  			l = 8
   244  		}
   245  
   246  		Lputb(uint32(addr))
   247  		Cput(uint8(t + 0x80)) /* 0x80 is variable length */
   248  
   249  		var i int
   250  		if t == 'z' || t == 'Z' {
   251  			Cput(uint8(s[0]))
   252  			for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 {
   253  				Cput(uint8(s[i]))
   254  				Cput(uint8(s[i+1]))
   255  			}
   256  
   257  			Cput(0)
   258  			Cput(0)
   259  			i++
   260  		} else {
   261  			/* skip the '<' in filenames */
   262  			if t == 'f' {
   263  				s = s[1:]
   264  			}
   265  			for i = 0; i < len(s); i++ {
   266  				Cput(uint8(s[i]))
   267  			}
   268  			Cput(0)
   269  		}
   270  
   271  		Symsize += int32(l) + 1 + int32(i) + 1
   272  
   273  	default:
   274  		return
   275  	}
   276  }
   277  
   278  func Asmplan9sym() {
   279  	genasmsym(putplan9sym)
   280  }
   281  
   282  var symt *LSym
   283  
   284  func Wputl(w uint16) {
   285  	Cput(uint8(w))
   286  	Cput(uint8(w >> 8))
   287  }
   288  
   289  func Wputb(w uint16) {
   290  	Cput(uint8(w >> 8))
   291  	Cput(uint8(w))
   292  }
   293  
   294  func Lputb(l uint32) {
   295  	Cput(uint8(l >> 24))
   296  	Cput(uint8(l >> 16))
   297  	Cput(uint8(l >> 8))
   298  	Cput(uint8(l))
   299  }
   300  
   301  func Lputl(l uint32) {
   302  	Cput(uint8(l))
   303  	Cput(uint8(l >> 8))
   304  	Cput(uint8(l >> 16))
   305  	Cput(uint8(l >> 24))
   306  }
   307  
   308  func Vputb(v uint64) {
   309  	Lputb(uint32(v >> 32))
   310  	Lputb(uint32(v))
   311  }
   312  
   313  func Vputl(v uint64) {
   314  	Lputl(uint32(v))
   315  	Lputl(uint32(v >> 32))
   316  }
   317  
   318  type byPkg []*Library
   319  
   320  func (libs byPkg) Len() int {
   321  	return len(libs)
   322  }
   323  
   324  func (libs byPkg) Less(a, b int) bool {
   325  	return libs[a].Pkg < libs[b].Pkg
   326  }
   327  
   328  func (libs byPkg) Swap(a, b int) {
   329  	libs[a], libs[b] = libs[b], libs[a]
   330  }
   331  
   332  func symtab() {
   333  	dosymtype()
   334  
   335  	// Define these so that they'll get put into the symbol table.
   336  	// data.c:/^address will provide the actual values.
   337  	xdefine("runtime.text", obj.STEXT, 0)
   338  
   339  	xdefine("runtime.etext", obj.STEXT, 0)
   340  	xdefine("runtime.typelink", obj.SRODATA, 0)
   341  	xdefine("runtime.etypelink", obj.SRODATA, 0)
   342  	xdefine("runtime.rodata", obj.SRODATA, 0)
   343  	xdefine("runtime.erodata", obj.SRODATA, 0)
   344  	xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
   345  	xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
   346  	xdefine("runtime.data", obj.SDATA, 0)
   347  	xdefine("runtime.edata", obj.SDATA, 0)
   348  	xdefine("runtime.bss", obj.SBSS, 0)
   349  	xdefine("runtime.ebss", obj.SBSS, 0)
   350  	xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0)
   351  	xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0)
   352  	xdefine("runtime.end", obj.SBSS, 0)
   353  	xdefine("runtime.epclntab", obj.SRODATA, 0)
   354  	xdefine("runtime.esymtab", obj.SRODATA, 0)
   355  
   356  	// garbage collection symbols
   357  	s := Linklookup(Ctxt, "runtime.gcdata", 0)
   358  
   359  	s.Type = obj.SRODATA
   360  	s.Size = 0
   361  	s.Reachable = true
   362  	xdefine("runtime.egcdata", obj.SRODATA, 0)
   363  
   364  	s = Linklookup(Ctxt, "runtime.gcbss", 0)
   365  	s.Type = obj.SRODATA
   366  	s.Size = 0
   367  	s.Reachable = true
   368  	xdefine("runtime.egcbss", obj.SRODATA, 0)
   369  
   370  	// pseudo-symbols to mark locations of type, string, and go string data.
   371  	var symtype *LSym
   372  	var symtyperel *LSym
   373  	if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
   374  		s = Linklookup(Ctxt, "type.*", 0)
   375  
   376  		s.Type = obj.STYPE
   377  		s.Size = 0
   378  		s.Reachable = true
   379  		symtype = s
   380  
   381  		s = Linklookup(Ctxt, "typerel.*", 0)
   382  
   383  		s.Type = obj.STYPERELRO
   384  		s.Size = 0
   385  		s.Reachable = true
   386  		symtyperel = s
   387  	} else if !DynlinkingGo() {
   388  		s = Linklookup(Ctxt, "type.*", 0)
   389  
   390  		s.Type = obj.STYPE
   391  		s.Size = 0
   392  		s.Reachable = true
   393  		symtype = s
   394  		symtyperel = s
   395  	}
   396  
   397  	s = Linklookup(Ctxt, "go.string.*", 0)
   398  	s.Type = obj.SGOSTRING
   399  	s.Local = true
   400  	s.Size = 0
   401  	s.Reachable = true
   402  	symgostring := s
   403  
   404  	s = Linklookup(Ctxt, "go.func.*", 0)
   405  	s.Type = obj.SGOFUNC
   406  	s.Local = true
   407  	s.Size = 0
   408  	s.Reachable = true
   409  	symgofunc := s
   410  
   411  	s = Linklookup(Ctxt, "runtime.gcbits.*", 0)
   412  	s.Type = obj.SGCBITS
   413  	s.Local = true
   414  	s.Size = 0
   415  	s.Reachable = true
   416  	symgcbits := s
   417  
   418  	symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
   419  	symtypelink.Type = obj.STYPELINK
   420  
   421  	symt = Linklookup(Ctxt, "runtime.symtab", 0)
   422  	symt.Local = true
   423  	symt.Type = obj.SSYMTAB
   424  	symt.Size = 0
   425  	symt.Reachable = true
   426  
   427  	ntypelinks := 0
   428  
   429  	// assign specific types so that they sort together.
   430  	// within a type they sort by size, so the .* symbols
   431  	// just defined above will be first.
   432  	// hide the specific symbols.
   433  	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
   434  		if !s.Reachable || s.Special != 0 || s.Type != obj.SRODATA {
   435  			continue
   436  		}
   437  
   438  		if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() {
   439  			s.Hide = 1
   440  			if UseRelro() && len(s.R) > 0 {
   441  				s.Type = obj.STYPERELRO
   442  				s.Outer = symtyperel
   443  			} else {
   444  				s.Type = obj.STYPE
   445  				s.Outer = symtype
   446  			}
   447  		}
   448  
   449  		if strings.HasPrefix(s.Name, "go.typelink.") {
   450  			ntypelinks++
   451  			s.Type = obj.STYPELINK
   452  			s.Hide = 1
   453  			s.Outer = symtypelink
   454  		}
   455  
   456  		if strings.HasPrefix(s.Name, "go.string.") {
   457  			s.Type = obj.SGOSTRING
   458  			s.Hide = 1
   459  			s.Outer = symgostring
   460  		}
   461  
   462  		if strings.HasPrefix(s.Name, "runtime.gcbits.") {
   463  			s.Type = obj.SGCBITS
   464  			s.Hide = 1
   465  			s.Outer = symgcbits
   466  		}
   467  
   468  		if strings.HasPrefix(s.Name, "go.func.") {
   469  			s.Type = obj.SGOFUNC
   470  			s.Hide = 1
   471  			s.Outer = symgofunc
   472  		}
   473  
   474  		if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals·") {
   475  			s.Type = obj.SGOFUNC
   476  			s.Hide = 1
   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.Reachable = true
   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(Ctxt.Nhistfile)+1)
   508  	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+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  	// The typelinks slice
   529  	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
   530  	adduint(Ctxt, moduledata, uint64(ntypelinks))
   531  	adduint(Ctxt, moduledata, uint64(ntypelinks))
   532  	if len(Ctxt.Shlibs) > 0 {
   533  		thismodulename := filepath.Base(outfile)
   534  		switch Buildmode {
   535  		case BuildmodeExe, BuildmodePIE:
   536  			// When linking an executable, outfile is just "a.out". Make
   537  			// it something slightly more comprehensible.
   538  			thismodulename = "the executable"
   539  		}
   540  		addgostring(moduledata, "go.link.thismodulename", thismodulename)
   541  
   542  		modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0)
   543  		modulehashes.Reachable = true
   544  		modulehashes.Local = true
   545  		modulehashes.Type = obj.SRODATA
   546  
   547  		for i, shlib := range Ctxt.Shlibs {
   548  			// modulehashes[i].modulename
   549  			modulename := filepath.Base(shlib.Path)
   550  			addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   551  
   552  			// modulehashes[i].linktimehash
   553  			addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   554  
   555  			// modulehashes[i].runtimehash
   556  			abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0)
   557  			abihash.Reachable = true
   558  			Addaddr(Ctxt, modulehashes, abihash)
   559  		}
   560  
   561  		Addaddr(Ctxt, moduledata, modulehashes)
   562  		adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
   563  		adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
   564  	}
   565  	// The rest of moduledata is zero initialized.
   566  	// When linking an object that does not contain the runtime we are
   567  	// creating the moduledata from scratch and it does not have a
   568  	// compiler-provided size, so read it from the type data.
   569  	moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0)
   570  	moduledata.Size = decodetype_size(moduledatatype)
   571  	Symgrow(Ctxt, moduledata, moduledata.Size)
   572  
   573  	lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0)
   574  	if lastmoduledatap.Type != obj.SDYNIMPORT {
   575  		lastmoduledatap.Type = obj.SNOPTRDATA
   576  		lastmoduledatap.Size = 0 // overwrite existing value
   577  		Addaddr(Ctxt, lastmoduledatap, moduledata)
   578  	}
   579  }