github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/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  	off := len(Elfstrdat)
    50  	Elfstrdat = append(Elfstrdat, s...)
    51  	Elfstrdat = append(Elfstrdat, 0)
    52  	return off
    53  }
    54  
    55  func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
    56  	if elf64 {
    57  		Thearch.Lput(uint32(off))
    58  		Cput(uint8(info))
    59  		Cput(uint8(other))
    60  		Thearch.Wput(uint16(shndx))
    61  		Thearch.Vput(uint64(addr))
    62  		Thearch.Vput(uint64(size))
    63  		Symsize += ELF64SYMSIZE
    64  	} else {
    65  		Thearch.Lput(uint32(off))
    66  		Thearch.Lput(uint32(addr))
    67  		Thearch.Lput(uint32(size))
    68  		Cput(uint8(info))
    69  		Cput(uint8(other))
    70  		Thearch.Wput(uint16(shndx))
    71  		Symsize += ELF32SYMSIZE
    72  	}
    73  }
    74  
    75  var numelfsym int = 1 // 0 is reserved
    76  
    77  var elfbind int
    78  
    79  func putelfsym(ctxt *Link, x *Symbol, s string, t int, addr int64, size int64, ver int, go_ *Symbol) {
    80  	var type_ int
    81  
    82  	switch t {
    83  	default:
    84  		return
    85  
    86  	case 'T':
    87  		type_ = STT_FUNC
    88  
    89  	case 'D':
    90  		type_ = STT_OBJECT
    91  
    92  	case 'B':
    93  		type_ = STT_OBJECT
    94  
    95  	case 'U':
    96  		// ElfType is only set for symbols read from Go shared libraries, but
    97  		// for other symbols it is left as STT_NOTYPE which is fine.
    98  		type_ = int(x.ElfType)
    99  
   100  	case 't':
   101  		type_ = STT_TLS
   102  	}
   103  
   104  	xo := x
   105  	for xo.Outer != nil {
   106  		xo = xo.Outer
   107  	}
   108  
   109  	var elfshnum int
   110  	if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ {
   111  		elfshnum = SHN_UNDEF
   112  	} else {
   113  		if xo.Sect == nil {
   114  			ctxt.Cursym = x
   115  			ctxt.Diag("missing section in putelfsym")
   116  			return
   117  		}
   118  		if xo.Sect.Elfsect == nil {
   119  			ctxt.Cursym = x
   120  			ctxt.Diag("missing ELF section in putelfsym")
   121  			return
   122  		}
   123  		elfshnum = xo.Sect.Elfsect.shnum
   124  	}
   125  
   126  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   127  	// maybe one day STB_WEAK.
   128  	bind := STB_GLOBAL
   129  
   130  	if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Attr.Local() {
   131  		bind = STB_LOCAL
   132  	}
   133  
   134  	// In external linking mode, we have to invoke gcc with -rdynamic
   135  	// to get the exported symbols put into the dynamic symbol table.
   136  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   137  	// mark all Go symbols local (not global) in the final executable.
   138  	// But when we're dynamically linking, we need all those global symbols.
   139  	if !ctxt.DynlinkingGo() && Linkmode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF {
   140  		bind = STB_LOCAL
   141  	}
   142  
   143  	if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
   144  		addr -= int64(xo.Sect.Vaddr)
   145  	}
   146  	other := STV_DEFAULT
   147  	if x.Type&obj.SHIDDEN != 0 {
   148  		other = STV_HIDDEN
   149  	}
   150  	if (Buildmode == BuildmodeCArchive || Buildmode == BuildmodePIE || ctxt.DynlinkingGo()) && SysArch.Family == sys.PPC64 && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
   151  		// On ppc64 the top three bits of the st_other field indicate how
   152  		// many instructions separate the global and local entry points. In
   153  		// our case it is two instructions, indicated by the value 3.
   154  		other |= 3 << 5
   155  	}
   156  
   157  	// When dynamically linking, we create Symbols by reading the names from
   158  	// the symbol tables of the shared libraries and so the names need to
   159  	// match exactly. Tools like DTrace will have to wait for now.
   160  	if !ctxt.DynlinkingGo() {
   161  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
   162  		s = strings.Replace(s, "·", ".", -1)
   163  	}
   164  
   165  	if ctxt.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  		// (*Symbol).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 *Symbol, 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(ctxt *Link) {
   194  	// the first symbol entry is reserved
   195  	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
   196  
   197  	dwarfaddelfsectionsyms(ctxt)
   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(ctxt, putelfsym)
   208  
   209  	elfbind = STB_GLOBAL
   210  	elfglobalsymndx = numelfsym
   211  	genasmsym(ctxt, putelfsym)
   212  }
   213  
   214  func putplan9sym(ctxt *Link, x *Symbol, s string, t int, addr int64, size int64, ver int, go_ *Symbol) {
   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 && !Flag8 {
   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(ctxt *Link) {
   267  	genasmsym(ctxt, putplan9sym)
   268  }
   269  
   270  var symt *Symbol
   271  
   272  var encbuf [10]byte
   273  
   274  func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) }
   275  func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) }
   276  func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) }
   277  
   278  func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) }
   279  func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) }
   280  func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) }
   281  
   282  func Append16b(b []byte, v uint16) []byte {
   283  	return append(b, uint8(v>>8), uint8(v))
   284  }
   285  func Append16l(b []byte, v uint16) []byte {
   286  	return append(b, uint8(v), uint8(v>>8))
   287  }
   288  
   289  func Append32b(b []byte, v uint32) []byte {
   290  	return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
   291  }
   292  func Append32l(b []byte, v uint32) []byte {
   293  	return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24))
   294  }
   295  
   296  func Append64b(b []byte, v uint64) []byte {
   297  	return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32),
   298  		uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
   299  }
   300  
   301  func Append64l(b []byte, v uint64) []byte {
   302  	return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24),
   303  		uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56))
   304  }
   305  
   306  type byPkg []*Library
   307  
   308  func (libs byPkg) Len() int {
   309  	return len(libs)
   310  }
   311  
   312  func (libs byPkg) Less(a, b int) bool {
   313  	return libs[a].Pkg < libs[b].Pkg
   314  }
   315  
   316  func (libs byPkg) Swap(a, b int) {
   317  	libs[a], libs[b] = libs[b], libs[a]
   318  }
   319  
   320  func (ctxt *Link) symtab() {
   321  	dosymtype(ctxt)
   322  
   323  	// Define these so that they'll get put into the symbol table.
   324  	// data.c:/^address will provide the actual values.
   325  	ctxt.xdefine("runtime.text", obj.STEXT, 0)
   326  
   327  	ctxt.xdefine("runtime.etext", obj.STEXT, 0)
   328  	ctxt.xdefine("runtime.typelink", obj.SRODATA, 0)
   329  	ctxt.xdefine("runtime.etypelink", obj.SRODATA, 0)
   330  	ctxt.xdefine("runtime.itablink", obj.SRODATA, 0)
   331  	ctxt.xdefine("runtime.eitablink", obj.SRODATA, 0)
   332  	ctxt.xdefine("runtime.rodata", obj.SRODATA, 0)
   333  	ctxt.xdefine("runtime.erodata", obj.SRODATA, 0)
   334  	ctxt.xdefine("runtime.types", obj.SRODATA, 0)
   335  	ctxt.xdefine("runtime.etypes", obj.SRODATA, 0)
   336  	ctxt.xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
   337  	ctxt.xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
   338  	ctxt.xdefine("runtime.data", obj.SDATA, 0)
   339  	ctxt.xdefine("runtime.edata", obj.SDATA, 0)
   340  	ctxt.xdefine("runtime.bss", obj.SBSS, 0)
   341  	ctxt.xdefine("runtime.ebss", obj.SBSS, 0)
   342  	ctxt.xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0)
   343  	ctxt.xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0)
   344  	ctxt.xdefine("runtime.end", obj.SBSS, 0)
   345  	ctxt.xdefine("runtime.epclntab", obj.SRODATA, 0)
   346  	ctxt.xdefine("runtime.esymtab", obj.SRODATA, 0)
   347  
   348  	// garbage collection symbols
   349  	s := Linklookup(ctxt, "runtime.gcdata", 0)
   350  
   351  	s.Type = obj.SRODATA
   352  	s.Size = 0
   353  	s.Attr |= AttrReachable
   354  	ctxt.xdefine("runtime.egcdata", obj.SRODATA, 0)
   355  
   356  	s = Linklookup(ctxt, "runtime.gcbss", 0)
   357  	s.Type = obj.SRODATA
   358  	s.Size = 0
   359  	s.Attr |= AttrReachable
   360  	ctxt.xdefine("runtime.egcbss", obj.SRODATA, 0)
   361  
   362  	// pseudo-symbols to mark locations of type, string, and go string data.
   363  	var symtype *Symbol
   364  	var symtyperel *Symbol
   365  	if UseRelro() && (Buildmode == BuildmodeCArchive || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
   366  		s = Linklookup(ctxt, "type.*", 0)
   367  
   368  		s.Type = obj.STYPE
   369  		s.Size = 0
   370  		s.Attr |= AttrReachable
   371  		symtype = s
   372  
   373  		s = Linklookup(ctxt, "typerel.*", 0)
   374  
   375  		s.Type = obj.STYPERELRO
   376  		s.Size = 0
   377  		s.Attr |= AttrReachable
   378  		symtyperel = s
   379  	} else if !ctxt.DynlinkingGo() {
   380  		s = Linklookup(ctxt, "type.*", 0)
   381  
   382  		s.Type = obj.STYPE
   383  		s.Size = 0
   384  		s.Attr |= AttrReachable
   385  		symtype = s
   386  		symtyperel = s
   387  	}
   388  
   389  	groupSym := func(name string, t int16) *Symbol {
   390  		s := Linklookup(ctxt, name, 0)
   391  		s.Type = t
   392  		s.Size = 0
   393  		s.Attr |= AttrLocal | AttrReachable
   394  		return s
   395  	}
   396  	var (
   397  		symgostring    = groupSym("go.string.*", obj.SGOSTRING)
   398  		symgostringhdr = groupSym("go.string.hdr.*", obj.SGOSTRINGHDR)
   399  		symgofunc      = groupSym("go.func.*", obj.SGOFUNC)
   400  		symgcbits      = groupSym("runtime.gcbits.*", obj.SGCBITS)
   401  	)
   402  
   403  	var symgofuncrel *Symbol
   404  	if !ctxt.DynlinkingGo() {
   405  		if UseRelro() {
   406  			symgofuncrel = groupSym("go.funcrel.*", obj.SGOFUNCRELRO)
   407  		} else {
   408  			symgofuncrel = symgofunc
   409  		}
   410  	}
   411  
   412  	symtypelink := Linklookup(ctxt, "runtime.typelink", 0)
   413  	symtypelink.Type = obj.STYPELINK
   414  
   415  	symitablink := Linklookup(ctxt, "runtime.itablink", 0)
   416  	symitablink.Type = obj.SITABLINK
   417  
   418  	symt = Linklookup(ctxt, "runtime.symtab", 0)
   419  	symt.Attr |= AttrLocal
   420  	symt.Type = obj.SSYMTAB
   421  	symt.Size = 0
   422  	symt.Attr |= AttrReachable
   423  
   424  	ntypelinks := 0
   425  	nitablinks := 0
   426  
   427  	// assign specific types so that they sort together.
   428  	// within a type they sort by size, so the .* symbols
   429  	// just defined above will be first.
   430  	// hide the specific symbols.
   431  	for _, s := range ctxt.Allsym {
   432  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != obj.SRODATA {
   433  			continue
   434  		}
   435  
   436  		switch {
   437  		case strings.HasPrefix(s.Name, "type."):
   438  			if !ctxt.DynlinkingGo() {
   439  				s.Attr |= AttrHidden
   440  			}
   441  			if UseRelro() {
   442  				s.Type = obj.STYPERELRO
   443  				s.Outer = symtyperel
   444  			} else {
   445  				s.Type = obj.STYPE
   446  				s.Outer = symtype
   447  			}
   448  
   449  		case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro():
   450  			// Keep go.importpath symbols in the same section as types and
   451  			// names, as they can be referred to by a section offset.
   452  			s.Type = obj.STYPERELRO
   453  
   454  		case strings.HasPrefix(s.Name, "go.typelink."):
   455  			ntypelinks++
   456  			s.Type = obj.STYPELINK
   457  			s.Attr |= AttrHidden
   458  			s.Outer = symtypelink
   459  
   460  		case strings.HasPrefix(s.Name, "go.itablink."):
   461  			nitablinks++
   462  			s.Type = obj.SITABLINK
   463  			s.Attr |= AttrHidden
   464  			s.Outer = symitablink
   465  
   466  		case strings.HasPrefix(s.Name, "go.string."):
   467  			s.Type = obj.SGOSTRING
   468  			s.Attr |= AttrHidden
   469  			s.Outer = symgostring
   470  			if strings.HasPrefix(s.Name, "go.string.hdr.") {
   471  				s.Type = obj.SGOSTRINGHDR
   472  				s.Outer = symgostringhdr
   473  			}
   474  
   475  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   476  			s.Type = obj.SGCBITS
   477  			s.Attr |= AttrHidden
   478  			s.Outer = symgcbits
   479  
   480  		case strings.HasSuffix(s.Name, "·f"):
   481  			if !ctxt.DynlinkingGo() {
   482  				s.Attr |= AttrHidden
   483  			}
   484  			if UseRelro() {
   485  				s.Type = obj.SGOFUNCRELRO
   486  				s.Outer = symgofuncrel
   487  			} else {
   488  				s.Type = obj.SGOFUNC
   489  				s.Outer = symgofunc
   490  			}
   491  
   492  		case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"):
   493  			s.Type = obj.SGOFUNC
   494  			s.Attr |= AttrHidden
   495  			s.Outer = symgofunc
   496  			s.Align = 4
   497  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   498  		}
   499  	}
   500  
   501  	if Buildmode == BuildmodeShared {
   502  		abihashgostr := Linklookup(ctxt, "go.link.abihash."+filepath.Base(*flagOutfile), 0)
   503  		abihashgostr.Attr |= AttrReachable
   504  		abihashgostr.Type = obj.SRODATA
   505  		hashsym := Linklookup(ctxt, "go.link.abihashbytes", 0)
   506  		Addaddr(ctxt, abihashgostr, hashsym)
   507  		adduint(ctxt, abihashgostr, uint64(hashsym.Size))
   508  	}
   509  
   510  	// Information about the layout of the executable image for the
   511  	// runtime to use. Any changes here must be matched by changes to
   512  	// the definition of moduledata in runtime/symtab.go.
   513  	// This code uses several global variables that are set by pcln.go:pclntab.
   514  	moduledata := ctxt.Moduledata
   515  	// The pclntab slice
   516  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.pclntab", 0))
   517  	adduint(ctxt, moduledata, uint64(Linklookup(ctxt, "runtime.pclntab", 0).Size))
   518  	adduint(ctxt, moduledata, uint64(Linklookup(ctxt, "runtime.pclntab", 0).Size))
   519  	// The ftab slice
   520  	Addaddrplus(ctxt, moduledata, Linklookup(ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset))
   521  	adduint(ctxt, moduledata, uint64(pclntabNfunc+1))
   522  	adduint(ctxt, moduledata, uint64(pclntabNfunc+1))
   523  	// The filetab slice
   524  	Addaddrplus(ctxt, moduledata, Linklookup(ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
   525  	adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1)
   526  	adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1)
   527  	// findfunctab
   528  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.findfunctab", 0))
   529  	// minpc, maxpc
   530  	Addaddr(ctxt, moduledata, pclntabFirstFunc)
   531  	Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
   532  	// pointers to specific parts of the module
   533  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.text", 0))
   534  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.etext", 0))
   535  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.noptrdata", 0))
   536  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.enoptrdata", 0))
   537  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.data", 0))
   538  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.edata", 0))
   539  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.bss", 0))
   540  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.ebss", 0))
   541  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.noptrbss", 0))
   542  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.enoptrbss", 0))
   543  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.end", 0))
   544  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.gcdata", 0))
   545  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.gcbss", 0))
   546  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.types", 0))
   547  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.etypes", 0))
   548  	// The typelinks slice
   549  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.typelink", 0))
   550  	adduint(ctxt, moduledata, uint64(ntypelinks))
   551  	adduint(ctxt, moduledata, uint64(ntypelinks))
   552  	// The itablinks slice
   553  	Addaddr(ctxt, moduledata, Linklookup(ctxt, "runtime.itablink", 0))
   554  	adduint(ctxt, moduledata, uint64(nitablinks))
   555  	adduint(ctxt, moduledata, uint64(nitablinks))
   556  	if len(ctxt.Shlibs) > 0 {
   557  		thismodulename := filepath.Base(*flagOutfile)
   558  		switch Buildmode {
   559  		case BuildmodeExe, BuildmodePIE:
   560  			// When linking an executable, outfile is just "a.out". Make
   561  			// it something slightly more comprehensible.
   562  			thismodulename = "the executable"
   563  		}
   564  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   565  
   566  		modulehashes := Linklookup(ctxt, "go.link.abihashes", 0)
   567  		modulehashes.Attr |= AttrReachable
   568  		modulehashes.Attr |= AttrLocal
   569  		modulehashes.Type = obj.SRODATA
   570  
   571  		for i, shlib := range ctxt.Shlibs {
   572  			// modulehashes[i].modulename
   573  			modulename := filepath.Base(shlib.Path)
   574  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   575  
   576  			// modulehashes[i].linktimehash
   577  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   578  
   579  			// modulehashes[i].runtimehash
   580  			abihash := Linklookup(ctxt, "go.link.abihash."+modulename, 0)
   581  			abihash.Attr |= AttrReachable
   582  			Addaddr(ctxt, modulehashes, abihash)
   583  		}
   584  
   585  		Addaddr(ctxt, moduledata, modulehashes)
   586  		adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs)))
   587  		adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs)))
   588  	}
   589  
   590  	// The rest of moduledata is zero initialized.
   591  	// When linking an object that does not contain the runtime we are
   592  	// creating the moduledata from scratch and it does not have a
   593  	// compiler-provided size, so read it from the type data.
   594  	moduledatatype := Linkrlookup(ctxt, "type.runtime.moduledata", 0)
   595  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   596  	Symgrow(ctxt, moduledata, moduledata.Size)
   597  
   598  	lastmoduledatap := Linklookup(ctxt, "runtime.lastmoduledatap", 0)
   599  	if lastmoduledatap.Type != obj.SDYNIMPORT {
   600  		lastmoduledatap.Type = obj.SNOPTRDATA
   601  		lastmoduledatap.Size = 0 // overwrite existing value
   602  		Addaddr(ctxt, lastmoduledatap, moduledata)
   603  	}
   604  }