github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/link/internal/ld/symtab.go (about)

     1  // Inferno utils/6l/span.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/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/objabi"
    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 SymbolType, addr int64, go_ *Symbol) {
    80  	var typ int
    81  
    82  	switch t {
    83  	default:
    84  		return
    85  
    86  	case TextSym:
    87  		typ = STT_FUNC
    88  
    89  	case DataSym, BSSSym:
    90  		typ = STT_OBJECT
    91  
    92  	case UndefinedSym:
    93  		// ElfType is only set for symbols read from Go shared libraries, but
    94  		// for other symbols it is left as STT_NOTYPE which is fine.
    95  		typ = int(x.ElfType)
    96  
    97  	case TLSSym:
    98  		typ = STT_TLS
    99  	}
   100  
   101  	size := x.Size
   102  	if t == UndefinedSym {
   103  		size = 0
   104  	}
   105  
   106  	xo := x
   107  	for xo.Outer != nil {
   108  		xo = xo.Outer
   109  	}
   110  
   111  	var elfshnum int
   112  	if xo.Type == SDYNIMPORT || xo.Type == SHOSTOBJ {
   113  		elfshnum = SHN_UNDEF
   114  	} else {
   115  		if xo.Sect == nil {
   116  			Errorf(x, "missing section in putelfsym")
   117  			return
   118  		}
   119  		if xo.Sect.Elfsect == nil {
   120  			Errorf(x, "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 x.Version != 0 || (x.Type&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&SHIDDEN != 0 {
   148  		other = STV_HIDDEN
   149  	}
   150  	if (Buildmode == BuildmodeCArchive || Buildmode == BuildmodePIE || ctxt.DynlinkingGo()) && SysArch.Family == sys.PPC64 && typ == 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 == 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|typ&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|typ&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, typ SymbolType, addr int64, go_ *Symbol) {
   215  	t := int(typ)
   216  	switch typ {
   217  	case TextSym, DataSym, BSSSym:
   218  		if x.Version != 0 {
   219  			t += 'a' - 'A'
   220  		}
   221  		fallthrough
   222  
   223  	case AutoSym, ParamSym, FileSym, FrameSym:
   224  		l := 4
   225  		if Headtype == objabi.Hplan9 && SysArch.Family == sys.AMD64 && !Flag8 {
   226  			Lputb(uint32(addr >> 32))
   227  			l = 8
   228  		}
   229  
   230  		Lputb(uint32(addr))
   231  		Cput(uint8(t + 0x80)) /* 0x80 is variable length */
   232  
   233  		var i int
   234  
   235  		/* skip the '<' in filenames */
   236  		if t == FileSym {
   237  			s = s[1:]
   238  		}
   239  		for i = 0; i < len(s); i++ {
   240  			Cput(s[i])
   241  		}
   242  		Cput(0)
   243  
   244  		Symsize += int32(l) + 1 + int32(i) + 1
   245  
   246  	default:
   247  		return
   248  	}
   249  }
   250  
   251  func Asmplan9sym(ctxt *Link) {
   252  	genasmsym(ctxt, putplan9sym)
   253  }
   254  
   255  var symt *Symbol
   256  
   257  var encbuf [10]byte
   258  
   259  func Wputb(w uint16) { Cwrite(Append16b(encbuf[:0], w)) }
   260  func Lputb(l uint32) { Cwrite(Append32b(encbuf[:0], l)) }
   261  func Vputb(v uint64) { Cwrite(Append64b(encbuf[:0], v)) }
   262  
   263  func Wputl(w uint16) { Cwrite(Append16l(encbuf[:0], w)) }
   264  func Lputl(l uint32) { Cwrite(Append32l(encbuf[:0], l)) }
   265  func Vputl(v uint64) { Cwrite(Append64l(encbuf[:0], v)) }
   266  
   267  func Append16b(b []byte, v uint16) []byte {
   268  	return append(b, uint8(v>>8), uint8(v))
   269  }
   270  func Append16l(b []byte, v uint16) []byte {
   271  	return append(b, uint8(v), uint8(v>>8))
   272  }
   273  
   274  func Append32b(b []byte, v uint32) []byte {
   275  	return append(b, uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
   276  }
   277  func Append32l(b []byte, v uint32) []byte {
   278  	return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24))
   279  }
   280  
   281  func Append64b(b []byte, v uint64) []byte {
   282  	return append(b, uint8(v>>56), uint8(v>>48), uint8(v>>40), uint8(v>>32),
   283  		uint8(v>>24), uint8(v>>16), uint8(v>>8), uint8(v))
   284  }
   285  
   286  func Append64l(b []byte, v uint64) []byte {
   287  	return append(b, uint8(v), uint8(v>>8), uint8(v>>16), uint8(v>>24),
   288  		uint8(v>>32), uint8(v>>40), uint8(v>>48), uint8(v>>56))
   289  }
   290  
   291  type byPkg []*Library
   292  
   293  func (libs byPkg) Len() int {
   294  	return len(libs)
   295  }
   296  
   297  func (libs byPkg) Less(a, b int) bool {
   298  	return libs[a].Pkg < libs[b].Pkg
   299  }
   300  
   301  func (libs byPkg) Swap(a, b int) {
   302  	libs[a], libs[b] = libs[b], libs[a]
   303  }
   304  
   305  // Create a table with information on the text sections.
   306  
   307  func textsectionmap(ctxt *Link) uint32 {
   308  
   309  	t := ctxt.Syms.Lookup("runtime.textsectionmap", 0)
   310  	t.Type = SRODATA
   311  	t.Attr |= AttrReachable
   312  	nsections := int64(0)
   313  
   314  	for _, sect := range Segtext.Sections {
   315  		if sect.Name == ".text" {
   316  			nsections++
   317  		} else {
   318  			break
   319  		}
   320  	}
   321  	Symgrow(t, 3*nsections*int64(SysArch.PtrSize))
   322  
   323  	off := int64(0)
   324  	n := 0
   325  
   326  	// The vaddr for each text section is the difference between the section's
   327  	// Vaddr and the Vaddr for the first text section as determined at compile
   328  	// time.
   329  
   330  	// The symbol for the first text section is named runtime.text as before.
   331  	// Additional text sections are named runtime.text.n where n is the
   332  	// order of creation starting with 1. These symbols provide the section's
   333  	// address after relocation by the linker.
   334  
   335  	textbase := Segtext.Sections[0].Vaddr
   336  	for _, sect := range Segtext.Sections {
   337  		if sect.Name != ".text" {
   338  			break
   339  		}
   340  		off = setuint(ctxt, t, off, sect.Vaddr-textbase)
   341  		off = setuint(ctxt, t, off, sect.Length)
   342  		if n == 0 {
   343  			s := ctxt.Syms.ROLookup("runtime.text", 0)
   344  			if s == nil {
   345  				Errorf(nil, "Unable to find symbol runtime.text\n")
   346  			}
   347  			off = setaddr(ctxt, t, off, s)
   348  
   349  		} else {
   350  			s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
   351  			if s == nil {
   352  				Errorf(nil, "Unable to find symbol runtime.text.%d\n", n)
   353  			}
   354  			off = setaddr(ctxt, t, off, s)
   355  		}
   356  		n++
   357  	}
   358  	return uint32(n)
   359  }
   360  
   361  func (ctxt *Link) symtab() {
   362  	dosymtype(ctxt)
   363  
   364  	// Define these so that they'll get put into the symbol table.
   365  	// data.c:/^address will provide the actual values.
   366  	ctxt.xdefine("runtime.text", STEXT, 0)
   367  
   368  	ctxt.xdefine("runtime.etext", STEXT, 0)
   369  	ctxt.xdefine("runtime.itablink", SRODATA, 0)
   370  	ctxt.xdefine("runtime.eitablink", SRODATA, 0)
   371  	ctxt.xdefine("runtime.rodata", SRODATA, 0)
   372  	ctxt.xdefine("runtime.erodata", SRODATA, 0)
   373  	ctxt.xdefine("runtime.types", SRODATA, 0)
   374  	ctxt.xdefine("runtime.etypes", SRODATA, 0)
   375  	ctxt.xdefine("runtime.noptrdata", SNOPTRDATA, 0)
   376  	ctxt.xdefine("runtime.enoptrdata", SNOPTRDATA, 0)
   377  	ctxt.xdefine("runtime.data", SDATA, 0)
   378  	ctxt.xdefine("runtime.edata", SDATA, 0)
   379  	ctxt.xdefine("runtime.bss", SBSS, 0)
   380  	ctxt.xdefine("runtime.ebss", SBSS, 0)
   381  	ctxt.xdefine("runtime.noptrbss", SNOPTRBSS, 0)
   382  	ctxt.xdefine("runtime.enoptrbss", SNOPTRBSS, 0)
   383  	ctxt.xdefine("runtime.end", SBSS, 0)
   384  	ctxt.xdefine("runtime.epclntab", SRODATA, 0)
   385  	ctxt.xdefine("runtime.esymtab", SRODATA, 0)
   386  
   387  	// garbage collection symbols
   388  	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
   389  
   390  	s.Type = SRODATA
   391  	s.Size = 0
   392  	s.Attr |= AttrReachable
   393  	ctxt.xdefine("runtime.egcdata", SRODATA, 0)
   394  
   395  	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
   396  	s.Type = SRODATA
   397  	s.Size = 0
   398  	s.Attr |= AttrReachable
   399  	ctxt.xdefine("runtime.egcbss", SRODATA, 0)
   400  
   401  	// pseudo-symbols to mark locations of type, string, and go string data.
   402  	var symtype *Symbol
   403  	var symtyperel *Symbol
   404  	if UseRelro() && (Buildmode == BuildmodeCArchive || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
   405  		s = ctxt.Syms.Lookup("type.*", 0)
   406  
   407  		s.Type = STYPE
   408  		s.Size = 0
   409  		s.Attr |= AttrReachable
   410  		symtype = s
   411  
   412  		s = ctxt.Syms.Lookup("typerel.*", 0)
   413  
   414  		s.Type = STYPERELRO
   415  		s.Size = 0
   416  		s.Attr |= AttrReachable
   417  		symtyperel = s
   418  	} else if !ctxt.DynlinkingGo() {
   419  		s = ctxt.Syms.Lookup("type.*", 0)
   420  
   421  		s.Type = STYPE
   422  		s.Size = 0
   423  		s.Attr |= AttrReachable
   424  		symtype = s
   425  		symtyperel = s
   426  	}
   427  
   428  	groupSym := func(name string, t SymKind) *Symbol {
   429  		s := ctxt.Syms.Lookup(name, 0)
   430  		s.Type = t
   431  		s.Size = 0
   432  		s.Attr |= AttrLocal | AttrReachable
   433  		return s
   434  	}
   435  	var (
   436  		symgostring = groupSym("go.string.*", SGOSTRING)
   437  		symgofunc   = groupSym("go.func.*", SGOFUNC)
   438  		symgcbits   = groupSym("runtime.gcbits.*", SGCBITS)
   439  	)
   440  
   441  	var symgofuncrel *Symbol
   442  	if !ctxt.DynlinkingGo() {
   443  		if UseRelro() {
   444  			symgofuncrel = groupSym("go.funcrel.*", SGOFUNCRELRO)
   445  		} else {
   446  			symgofuncrel = symgofunc
   447  		}
   448  	}
   449  
   450  	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   451  	symitablink.Type = SITABLINK
   452  
   453  	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   454  	symt.Attr |= AttrLocal
   455  	symt.Type = SSYMTAB
   456  	symt.Size = 0
   457  	symt.Attr |= AttrReachable
   458  
   459  	nitablinks := 0
   460  
   461  	// assign specific types so that they sort together.
   462  	// within a type they sort by size, so the .* symbols
   463  	// just defined above will be first.
   464  	// hide the specific symbols.
   465  	for _, s := range ctxt.Syms.Allsym {
   466  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != SRODATA {
   467  			continue
   468  		}
   469  
   470  		switch {
   471  		case strings.HasPrefix(s.Name, "type."):
   472  			if !ctxt.DynlinkingGo() {
   473  				s.Attr |= AttrHidden
   474  			}
   475  			if UseRelro() {
   476  				s.Type = STYPERELRO
   477  				s.Outer = symtyperel
   478  			} else {
   479  				s.Type = STYPE
   480  				s.Outer = symtype
   481  			}
   482  
   483  		case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro():
   484  			// Keep go.importpath symbols in the same section as types and
   485  			// names, as they can be referred to by a section offset.
   486  			s.Type = STYPERELRO
   487  
   488  		case strings.HasPrefix(s.Name, "go.itablink."):
   489  			nitablinks++
   490  			s.Type = SITABLINK
   491  			s.Attr |= AttrHidden
   492  			s.Outer = symitablink
   493  
   494  		case strings.HasPrefix(s.Name, "go.string."):
   495  			s.Type = SGOSTRING
   496  			s.Attr |= AttrHidden
   497  			s.Outer = symgostring
   498  
   499  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   500  			s.Type = SGCBITS
   501  			s.Attr |= AttrHidden
   502  			s.Outer = symgcbits
   503  
   504  		case strings.HasSuffix(s.Name, "·f"):
   505  			if !ctxt.DynlinkingGo() {
   506  				s.Attr |= AttrHidden
   507  			}
   508  			if UseRelro() {
   509  				s.Type = SGOFUNCRELRO
   510  				s.Outer = symgofuncrel
   511  			} else {
   512  				s.Type = SGOFUNC
   513  				s.Outer = symgofunc
   514  			}
   515  
   516  		case strings.HasPrefix(s.Name, "gcargs."),
   517  			strings.HasPrefix(s.Name, "gclocals."),
   518  			strings.HasPrefix(s.Name, "gclocals·"),
   519  			strings.HasPrefix(s.Name, "inltree."):
   520  			s.Type = SGOFUNC
   521  			s.Attr |= AttrHidden
   522  			s.Outer = symgofunc
   523  			s.Align = 4
   524  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   525  		}
   526  	}
   527  
   528  	if Buildmode == BuildmodeShared {
   529  		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   530  		abihashgostr.Attr |= AttrReachable
   531  		abihashgostr.Type = SRODATA
   532  		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   533  		Addaddr(ctxt, abihashgostr, hashsym)
   534  		adduint(ctxt, abihashgostr, uint64(hashsym.Size))
   535  	}
   536  	if Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
   537  		for _, l := range ctxt.Library {
   538  			s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
   539  			s.Attr |= AttrReachable
   540  			s.Type = SRODATA
   541  			s.Size = int64(len(l.hash))
   542  			s.P = []byte(l.hash)
   543  			str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
   544  			str.Attr |= AttrReachable
   545  			str.Type = SRODATA
   546  			Addaddr(ctxt, str, s)
   547  			adduint(ctxt, str, uint64(len(l.hash)))
   548  		}
   549  	}
   550  
   551  	nsections := textsectionmap(ctxt)
   552  
   553  	// Information about the layout of the executable image for the
   554  	// runtime to use. Any changes here must be matched by changes to
   555  	// the definition of moduledata in runtime/symtab.go.
   556  	// This code uses several global variables that are set by pcln.go:pclntab.
   557  	moduledata := ctxt.Moduledata
   558  	// The pclntab slice
   559  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0))
   560  	adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   561  	adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   562  	// The ftab slice
   563  	Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   564  	adduint(ctxt, moduledata, uint64(pclntabNfunc+1))
   565  	adduint(ctxt, moduledata, uint64(pclntabNfunc+1))
   566  	// The filetab slice
   567  	Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   568  	adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1)
   569  	adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1)
   570  	// findfunctab
   571  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   572  	// minpc, maxpc
   573  	Addaddr(ctxt, moduledata, pclntabFirstFunc)
   574  	Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
   575  	// pointers to specific parts of the module
   576  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.text", 0))
   577  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etext", 0))
   578  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   579  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   580  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.data", 0))
   581  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.edata", 0))
   582  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.bss", 0))
   583  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.ebss", 0))
   584  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   585  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   586  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.end", 0))
   587  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcdata", 0))
   588  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcbss", 0))
   589  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.types", 0))
   590  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etypes", 0))
   591  
   592  	// text section information
   593  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   594  	adduint(ctxt, moduledata, uint64(nsections))
   595  	adduint(ctxt, moduledata, uint64(nsections))
   596  
   597  	// The typelinks slice
   598  	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   599  	ntypelinks := uint64(typelinkSym.Size) / 4
   600  	Addaddr(ctxt, moduledata, typelinkSym)
   601  	adduint(ctxt, moduledata, ntypelinks)
   602  	adduint(ctxt, moduledata, ntypelinks)
   603  	// The itablinks slice
   604  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.itablink", 0))
   605  	adduint(ctxt, moduledata, uint64(nitablinks))
   606  	adduint(ctxt, moduledata, uint64(nitablinks))
   607  	// The ptab slice
   608  	if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
   609  		ptab.Attr |= AttrLocal
   610  		ptab.Type = SRODATA
   611  
   612  		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   613  		Addaddr(ctxt, moduledata, ptab)
   614  		adduint(ctxt, moduledata, nentries)
   615  		adduint(ctxt, moduledata, nentries)
   616  	} else {
   617  		adduint(ctxt, moduledata, 0)
   618  		adduint(ctxt, moduledata, 0)
   619  		adduint(ctxt, moduledata, 0)
   620  	}
   621  	if Buildmode == BuildmodePlugin {
   622  		addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath)
   623  
   624  		pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
   625  		pkghashes.Attr |= AttrReachable
   626  		pkghashes.Attr |= AttrLocal
   627  		pkghashes.Type = SRODATA
   628  
   629  		for i, l := range ctxt.Library {
   630  			// pkghashes[i].name
   631  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   632  			// pkghashes[i].linktimehash
   633  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), string(l.hash))
   634  			// pkghashes[i].runtimehash
   635  			hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
   636  			Addaddr(ctxt, pkghashes, hash)
   637  		}
   638  		Addaddr(ctxt, moduledata, pkghashes)
   639  		adduint(ctxt, moduledata, uint64(len(ctxt.Library)))
   640  		adduint(ctxt, moduledata, uint64(len(ctxt.Library)))
   641  	} else {
   642  		adduint(ctxt, moduledata, 0) // pluginpath
   643  		adduint(ctxt, moduledata, 0)
   644  		adduint(ctxt, moduledata, 0) // pkghashes slice
   645  		adduint(ctxt, moduledata, 0)
   646  		adduint(ctxt, moduledata, 0)
   647  	}
   648  	if len(ctxt.Shlibs) > 0 {
   649  		thismodulename := filepath.Base(*flagOutfile)
   650  		switch Buildmode {
   651  		case BuildmodeExe, BuildmodePIE:
   652  			// When linking an executable, outfile is just "a.out". Make
   653  			// it something slightly more comprehensible.
   654  			thismodulename = "the executable"
   655  		}
   656  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   657  
   658  		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   659  		modulehashes.Attr |= AttrReachable
   660  		modulehashes.Attr |= AttrLocal
   661  		modulehashes.Type = SRODATA
   662  
   663  		for i, shlib := range ctxt.Shlibs {
   664  			// modulehashes[i].modulename
   665  			modulename := filepath.Base(shlib.Path)
   666  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   667  
   668  			// modulehashes[i].linktimehash
   669  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   670  
   671  			// modulehashes[i].runtimehash
   672  			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   673  			abihash.Attr |= AttrReachable
   674  			Addaddr(ctxt, modulehashes, abihash)
   675  		}
   676  
   677  		Addaddr(ctxt, moduledata, modulehashes)
   678  		adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs)))
   679  		adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs)))
   680  	}
   681  
   682  	// The rest of moduledata is zero initialized.
   683  	// When linking an object that does not contain the runtime we are
   684  	// creating the moduledata from scratch and it does not have a
   685  	// compiler-provided size, so read it from the type data.
   686  	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   687  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   688  	Symgrow(moduledata, moduledata.Size)
   689  
   690  	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   691  	if lastmoduledatap.Type != SDYNIMPORT {
   692  		lastmoduledatap.Type = SNOPTRDATA
   693  		lastmoduledatap.Size = 0 // overwrite existing value
   694  		Addaddr(ctxt, lastmoduledatap, moduledata)
   695  	}
   696  }