github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/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  	"cmd/link/internal/sym"
    37  	"fmt"
    38  	"path/filepath"
    39  	"strings"
    40  )
    41  
    42  // Symbol table.
    43  
    44  func putelfstr(s string) int {
    45  	if len(Elfstrdat) == 0 && s != "" {
    46  		// first entry must be empty string
    47  		putelfstr("")
    48  	}
    49  
    50  	off := len(Elfstrdat)
    51  	Elfstrdat = append(Elfstrdat, s...)
    52  	Elfstrdat = append(Elfstrdat, 0)
    53  	return off
    54  }
    55  
    56  func putelfsyment(out *OutBuf, off int, addr int64, size int64, info int, shndx int, other int) {
    57  	if elf64 {
    58  		out.Write32(uint32(off))
    59  		out.Write8(uint8(info))
    60  		out.Write8(uint8(other))
    61  		out.Write16(uint16(shndx))
    62  		out.Write64(uint64(addr))
    63  		out.Write64(uint64(size))
    64  		Symsize += ELF64SYMSIZE
    65  	} else {
    66  		out.Write32(uint32(off))
    67  		out.Write32(uint32(addr))
    68  		out.Write32(uint32(size))
    69  		out.Write8(uint8(info))
    70  		out.Write8(uint8(other))
    71  		out.Write16(uint16(shndx))
    72  		Symsize += ELF32SYMSIZE
    73  	}
    74  }
    75  
    76  var numelfsym = 1 // 0 is reserved
    77  
    78  var elfbind int
    79  
    80  func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go_ *sym.Symbol) {
    81  	var typ int
    82  
    83  	switch t {
    84  	default:
    85  		return
    86  
    87  	case TextSym:
    88  		typ = STT_FUNC
    89  
    90  	case DataSym, BSSSym:
    91  		typ = STT_OBJECT
    92  
    93  	case UndefinedSym:
    94  		// ElfType is only set for symbols read from Go shared libraries, but
    95  		// for other symbols it is left as STT_NOTYPE which is fine.
    96  		typ = int(x.ElfType)
    97  
    98  	case TLSSym:
    99  		typ = STT_TLS
   100  	}
   101  
   102  	size := x.Size
   103  	if t == UndefinedSym {
   104  		size = 0
   105  	}
   106  
   107  	xo := x
   108  	for xo.Outer != nil {
   109  		xo = xo.Outer
   110  	}
   111  
   112  	var elfshnum int
   113  	if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ {
   114  		elfshnum = SHN_UNDEF
   115  	} else {
   116  		if xo.Sect == nil {
   117  			Errorf(x, "missing section in putelfsym")
   118  			return
   119  		}
   120  		if xo.Sect.Elfsect == nil {
   121  			Errorf(x, "missing ELF section in putelfsym")
   122  			return
   123  		}
   124  		elfshnum = xo.Sect.Elfsect.(*ElfShdr).shnum
   125  	}
   126  
   127  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   128  	// maybe one day STB_WEAK.
   129  	bind := STB_GLOBAL
   130  
   131  	if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
   132  		bind = STB_LOCAL
   133  	}
   134  
   135  	// In external linking mode, we have to invoke gcc with -rdynamic
   136  	// to get the exported symbols put into the dynamic symbol table.
   137  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   138  	// mark all Go symbols local (not global) in the final executable.
   139  	// But when we're dynamically linking, we need all those global symbols.
   140  	if !ctxt.DynlinkingGo() && ctxt.LinkMode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF {
   141  		bind = STB_LOCAL
   142  	}
   143  
   144  	if ctxt.LinkMode == LinkExternal && elfshnum != SHN_UNDEF {
   145  		addr -= int64(xo.Sect.Vaddr)
   146  	}
   147  	other := STV_DEFAULT
   148  	if x.Attr.VisibilityHidden() {
   149  		// TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when
   150  		// internally linking. But STV_HIDDEN visibility only matters in object
   151  		// files and shared libraries, and as we are a long way from implementing
   152  		// internal linking for shared libraries and only create object files when
   153  		// externally linking, I don't think this makes a lot of sense.
   154  		other = STV_HIDDEN
   155  	}
   156  	if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
   157  		// On ppc64 the top three bits of the st_other field indicate how
   158  		// many instructions separate the global and local entry points. In
   159  		// our case it is two instructions, indicated by the value 3.
   160  		// The conditions here match those in preprocess in
   161  		// cmd/internal/obj/ppc64/obj9.go, which is where the
   162  		// instructions are inserted.
   163  		other |= 3 << 5
   164  	}
   165  
   166  	// When dynamically linking, we create Symbols by reading the names from
   167  	// the symbol tables of the shared libraries and so the names need to
   168  	// match exactly. Tools like DTrace will have to wait for now.
   169  	if !ctxt.DynlinkingGo() {
   170  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
   171  		s = strings.Replace(s, "·", ".", -1)
   172  	}
   173  
   174  	if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == sym.STEXT {
   175  		// When dynamically linking, we want references to functions defined
   176  		// in this module to always be to the function object, not to the
   177  		// PLT. We force this by writing an additional local symbol for every
   178  		// global function symbol and making all relocations against the
   179  		// global symbol refer to this local symbol instead (see
   180  		// (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the
   181  		// ELF linker -Bsymbolic-functions option, but that is buggy on
   182  		// several platforms.
   183  		putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other)
   184  		x.LocalElfsym = int32(numelfsym)
   185  		numelfsym++
   186  		return
   187  	} else if bind != elfbind {
   188  		return
   189  	}
   190  
   191  	putelfsyment(ctxt.Out, putelfstr(s), addr, size, bind<<4|typ&0xf, elfshnum, other)
   192  	x.Elfsym = int32(numelfsym)
   193  	numelfsym++
   194  }
   195  
   196  func putelfsectionsym(out *OutBuf, s *sym.Symbol, shndx int) {
   197  	putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
   198  	s.Elfsym = int32(numelfsym)
   199  	numelfsym++
   200  }
   201  
   202  func Asmelfsym(ctxt *Link) {
   203  	// the first symbol entry is reserved
   204  	putelfsyment(ctxt.Out, 0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
   205  
   206  	dwarfaddelfsectionsyms(ctxt)
   207  
   208  	// Some linkers will add a FILE sym if one is not present.
   209  	// Avoid having the working directory inserted into the symbol table.
   210  	// It is added with a name to avoid problems with external linking
   211  	// encountered on some versions of Solaris. See issue #14957.
   212  	putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
   213  	numelfsym++
   214  
   215  	elfbind = STB_LOCAL
   216  	genasmsym(ctxt, putelfsym)
   217  
   218  	elfbind = STB_GLOBAL
   219  	elfglobalsymndx = numelfsym
   220  	genasmsym(ctxt, putelfsym)
   221  }
   222  
   223  func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64, go_ *sym.Symbol) {
   224  	t := int(typ)
   225  	switch typ {
   226  	case TextSym, DataSym, BSSSym:
   227  		if x.Version != 0 {
   228  			t += 'a' - 'A'
   229  		}
   230  		fallthrough
   231  
   232  	case AutoSym, ParamSym, FrameSym:
   233  		l := 4
   234  		if ctxt.HeadType == objabi.Hplan9 && ctxt.Arch.Family == sys.AMD64 && !Flag8 {
   235  			ctxt.Out.Write32b(uint32(addr >> 32))
   236  			l = 8
   237  		}
   238  
   239  		ctxt.Out.Write32b(uint32(addr))
   240  		ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */
   241  
   242  		ctxt.Out.WriteString(s)
   243  		ctxt.Out.Write8(0)
   244  
   245  		Symsize += int32(l) + 1 + int32(len(s)) + 1
   246  
   247  	default:
   248  		return
   249  	}
   250  }
   251  
   252  func Asmplan9sym(ctxt *Link) {
   253  	genasmsym(ctxt, putplan9sym)
   254  }
   255  
   256  var symt *sym.Symbol
   257  
   258  type byPkg []*sym.Library
   259  
   260  func (libs byPkg) Len() int {
   261  	return len(libs)
   262  }
   263  
   264  func (libs byPkg) Less(a, b int) bool {
   265  	return libs[a].Pkg < libs[b].Pkg
   266  }
   267  
   268  func (libs byPkg) Swap(a, b int) {
   269  	libs[a], libs[b] = libs[b], libs[a]
   270  }
   271  
   272  // Create a table with information on the text sections.
   273  
   274  func textsectionmap(ctxt *Link) uint32 {
   275  
   276  	t := ctxt.Syms.Lookup("runtime.textsectionmap", 0)
   277  	t.Type = sym.SRODATA
   278  	t.Attr |= sym.AttrReachable
   279  	nsections := int64(0)
   280  
   281  	for _, sect := range Segtext.Sections {
   282  		if sect.Name == ".text" {
   283  			nsections++
   284  		} else {
   285  			break
   286  		}
   287  	}
   288  	t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize))
   289  
   290  	off := int64(0)
   291  	n := 0
   292  
   293  	// The vaddr for each text section is the difference between the section's
   294  	// Vaddr and the Vaddr for the first text section as determined at compile
   295  	// time.
   296  
   297  	// The symbol for the first text section is named runtime.text as before.
   298  	// Additional text sections are named runtime.text.n where n is the
   299  	// order of creation starting with 1. These symbols provide the section's
   300  	// address after relocation by the linker.
   301  
   302  	textbase := Segtext.Sections[0].Vaddr
   303  	for _, sect := range Segtext.Sections {
   304  		if sect.Name != ".text" {
   305  			break
   306  		}
   307  		off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase)
   308  		off = t.SetUint(ctxt.Arch, off, sect.Length)
   309  		if n == 0 {
   310  			s := ctxt.Syms.ROLookup("runtime.text", 0)
   311  			if s == nil {
   312  				Errorf(nil, "Unable to find symbol runtime.text\n")
   313  			}
   314  			off = t.SetAddr(ctxt.Arch, off, s)
   315  
   316  		} else {
   317  			s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
   318  			if s == nil {
   319  				Errorf(nil, "Unable to find symbol runtime.text.%d\n", n)
   320  			}
   321  			off = t.SetAddr(ctxt.Arch, off, s)
   322  		}
   323  		n++
   324  	}
   325  	return uint32(n)
   326  }
   327  
   328  func (ctxt *Link) symtab() {
   329  	dosymtype(ctxt)
   330  
   331  	// Define these so that they'll get put into the symbol table.
   332  	// data.c:/^address will provide the actual values.
   333  	ctxt.xdefine("runtime.text", sym.STEXT, 0)
   334  
   335  	ctxt.xdefine("runtime.etext", sym.STEXT, 0)
   336  	ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
   337  	ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
   338  	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
   339  	ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
   340  	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
   341  	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
   342  	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
   343  	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
   344  	ctxt.xdefine("runtime.data", sym.SDATA, 0)
   345  	ctxt.xdefine("runtime.edata", sym.SDATA, 0)
   346  	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
   347  	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
   348  	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
   349  	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
   350  	ctxt.xdefine("runtime.end", sym.SBSS, 0)
   351  	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   352  	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
   353  
   354  	// garbage collection symbols
   355  	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
   356  
   357  	s.Type = sym.SRODATA
   358  	s.Size = 0
   359  	s.Attr |= sym.AttrReachable
   360  	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   361  
   362  	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
   363  	s.Type = sym.SRODATA
   364  	s.Size = 0
   365  	s.Attr |= sym.AttrReachable
   366  	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   367  
   368  	// pseudo-symbols to mark locations of type, string, and go string data.
   369  	var symtype *sym.Symbol
   370  	var symtyperel *sym.Symbol
   371  	if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   372  		s = ctxt.Syms.Lookup("type.*", 0)
   373  
   374  		s.Type = sym.STYPE
   375  		s.Size = 0
   376  		s.Attr |= sym.AttrReachable
   377  		symtype = s
   378  
   379  		s = ctxt.Syms.Lookup("typerel.*", 0)
   380  
   381  		s.Type = sym.STYPERELRO
   382  		s.Size = 0
   383  		s.Attr |= sym.AttrReachable
   384  		symtyperel = s
   385  	} else if !ctxt.DynlinkingGo() {
   386  		s = ctxt.Syms.Lookup("type.*", 0)
   387  
   388  		s.Type = sym.STYPE
   389  		s.Size = 0
   390  		s.Attr |= sym.AttrReachable
   391  		symtype = s
   392  		symtyperel = s
   393  	}
   394  
   395  	groupSym := func(name string, t sym.SymKind) *sym.Symbol {
   396  		s := ctxt.Syms.Lookup(name, 0)
   397  		s.Type = t
   398  		s.Size = 0
   399  		s.Attr |= sym.AttrLocal | sym.AttrReachable
   400  		return s
   401  	}
   402  	var (
   403  		symgostring = groupSym("go.string.*", sym.SGOSTRING)
   404  		symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
   405  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   406  	)
   407  
   408  	var symgofuncrel *sym.Symbol
   409  	if !ctxt.DynlinkingGo() {
   410  		if ctxt.UseRelro() {
   411  			symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
   412  		} else {
   413  			symgofuncrel = symgofunc
   414  		}
   415  	}
   416  
   417  	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   418  	symitablink.Type = sym.SITABLINK
   419  
   420  	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   421  	symt.Attr |= sym.AttrLocal
   422  	symt.Type = sym.SSYMTAB
   423  	symt.Size = 0
   424  	symt.Attr |= sym.AttrReachable
   425  
   426  	nitablinks := 0
   427  
   428  	// assign specific types so that they sort together.
   429  	// within a type they sort by size, so the .* symbols
   430  	// just defined above will be first.
   431  	// hide the specific symbols.
   432  	for _, s := range ctxt.Syms.Allsym {
   433  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
   434  			continue
   435  		}
   436  
   437  		switch {
   438  		case strings.HasPrefix(s.Name, "type."):
   439  			if !ctxt.DynlinkingGo() {
   440  				s.Attr |= sym.AttrNotInSymbolTable
   441  			}
   442  			if ctxt.UseRelro() {
   443  				s.Type = sym.STYPERELRO
   444  				s.Outer = symtyperel
   445  			} else {
   446  				s.Type = sym.STYPE
   447  				s.Outer = symtype
   448  			}
   449  
   450  		case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro():
   451  			// Keep go.importpath symbols in the same section as types and
   452  			// names, as they can be referred to by a section offset.
   453  			s.Type = sym.STYPERELRO
   454  
   455  		case strings.HasPrefix(s.Name, "go.itablink."):
   456  			nitablinks++
   457  			s.Type = sym.SITABLINK
   458  			s.Attr |= sym.AttrNotInSymbolTable
   459  			s.Outer = symitablink
   460  
   461  		case strings.HasPrefix(s.Name, "go.string."):
   462  			s.Type = sym.SGOSTRING
   463  			s.Attr |= sym.AttrNotInSymbolTable
   464  			s.Outer = symgostring
   465  
   466  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   467  			s.Type = sym.SGCBITS
   468  			s.Attr |= sym.AttrNotInSymbolTable
   469  			s.Outer = symgcbits
   470  
   471  		case strings.HasSuffix(s.Name, "·f"):
   472  			if !ctxt.DynlinkingGo() {
   473  				s.Attr |= sym.AttrNotInSymbolTable
   474  			}
   475  			if ctxt.UseRelro() {
   476  				s.Type = sym.SGOFUNCRELRO
   477  				s.Outer = symgofuncrel
   478  			} else {
   479  				s.Type = sym.SGOFUNC
   480  				s.Outer = symgofunc
   481  			}
   482  
   483  		case strings.HasPrefix(s.Name, "gcargs."),
   484  			strings.HasPrefix(s.Name, "gclocals."),
   485  			strings.HasPrefix(s.Name, "gclocals·"),
   486  			strings.HasPrefix(s.Name, "inltree."):
   487  			s.Type = sym.SGOFUNC
   488  			s.Attr |= sym.AttrNotInSymbolTable
   489  			s.Outer = symgofunc
   490  			s.Align = 4
   491  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   492  		}
   493  	}
   494  
   495  	if ctxt.BuildMode == BuildModeShared {
   496  		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   497  		abihashgostr.Attr |= sym.AttrReachable
   498  		abihashgostr.Type = sym.SRODATA
   499  		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   500  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   501  		abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
   502  	}
   503  	if ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
   504  		for _, l := range ctxt.Library {
   505  			s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
   506  			s.Attr |= sym.AttrReachable
   507  			s.Type = sym.SRODATA
   508  			s.Size = int64(len(l.Hash))
   509  			s.P = []byte(l.Hash)
   510  			str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
   511  			str.Attr |= sym.AttrReachable
   512  			str.Type = sym.SRODATA
   513  			str.AddAddr(ctxt.Arch, s)
   514  			str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
   515  		}
   516  	}
   517  
   518  	nsections := textsectionmap(ctxt)
   519  
   520  	// Information about the layout of the executable image for the
   521  	// runtime to use. Any changes here must be matched by changes to
   522  	// the definition of moduledata in runtime/symtab.go.
   523  	// This code uses several global variables that are set by pcln.go:pclntab.
   524  	moduledata := ctxt.Moduledata
   525  	// The pclntab slice
   526  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
   527  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   528  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   529  	// The ftab slice
   530  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   531  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   532  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   533  	// The filetab slice
   534  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   535  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   536  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   537  	// findfunctab
   538  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   539  	// minpc, maxpc
   540  	moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
   541  	moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size)
   542  	// pointers to specific parts of the module
   543  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
   544  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
   545  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   546  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   547  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
   548  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
   549  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
   550  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
   551  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   552  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   553  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
   554  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
   555  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
   556  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
   557  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
   558  
   559  	// text section information
   560  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   561  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   562  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   563  
   564  	// The typelinks slice
   565  	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   566  	ntypelinks := uint64(typelinkSym.Size) / 4
   567  	moduledata.AddAddr(ctxt.Arch, typelinkSym)
   568  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   569  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   570  	// The itablinks slice
   571  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0))
   572  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   573  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   574  	// The ptab slice
   575  	if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
   576  		ptab.Attr |= sym.AttrLocal
   577  		ptab.Type = sym.SRODATA
   578  
   579  		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   580  		moduledata.AddAddr(ctxt.Arch, ptab)
   581  		moduledata.AddUint(ctxt.Arch, nentries)
   582  		moduledata.AddUint(ctxt.Arch, nentries)
   583  	} else {
   584  		moduledata.AddUint(ctxt.Arch, 0)
   585  		moduledata.AddUint(ctxt.Arch, 0)
   586  		moduledata.AddUint(ctxt.Arch, 0)
   587  	}
   588  	if ctxt.BuildMode == BuildModePlugin {
   589  		addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   590  
   591  		pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
   592  		pkghashes.Attr |= sym.AttrReachable
   593  		pkghashes.Attr |= sym.AttrLocal
   594  		pkghashes.Type = sym.SRODATA
   595  
   596  		for i, l := range ctxt.Library {
   597  			// pkghashes[i].name
   598  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   599  			// pkghashes[i].linktimehash
   600  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
   601  			// pkghashes[i].runtimehash
   602  			hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
   603  			pkghashes.AddAddr(ctxt.Arch, hash)
   604  		}
   605  		moduledata.AddAddr(ctxt.Arch, pkghashes)
   606  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   607  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   608  	} else {
   609  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   610  		moduledata.AddUint(ctxt.Arch, 0)
   611  		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   612  		moduledata.AddUint(ctxt.Arch, 0)
   613  		moduledata.AddUint(ctxt.Arch, 0)
   614  	}
   615  	if len(ctxt.Shlibs) > 0 {
   616  		thismodulename := filepath.Base(*flagOutfile)
   617  		switch ctxt.BuildMode {
   618  		case BuildModeExe, BuildModePIE:
   619  			// When linking an executable, outfile is just "a.out". Make
   620  			// it something slightly more comprehensible.
   621  			thismodulename = "the executable"
   622  		}
   623  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   624  
   625  		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   626  		modulehashes.Attr |= sym.AttrReachable
   627  		modulehashes.Attr |= sym.AttrLocal
   628  		modulehashes.Type = sym.SRODATA
   629  
   630  		for i, shlib := range ctxt.Shlibs {
   631  			// modulehashes[i].modulename
   632  			modulename := filepath.Base(shlib.Path)
   633  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   634  
   635  			// modulehashes[i].linktimehash
   636  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   637  
   638  			// modulehashes[i].runtimehash
   639  			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   640  			abihash.Attr |= sym.AttrReachable
   641  			modulehashes.AddAddr(ctxt.Arch, abihash)
   642  		}
   643  
   644  		moduledata.AddAddr(ctxt.Arch, modulehashes)
   645  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   646  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   647  	} else {
   648  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   649  		moduledata.AddUint(ctxt.Arch, 0)
   650  		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   651  		moduledata.AddUint(ctxt.Arch, 0)
   652  		moduledata.AddUint(ctxt.Arch, 0)
   653  	}
   654  
   655  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   656  	if hasmain {
   657  		moduledata.AddUint8(1)
   658  	} else {
   659  		moduledata.AddUint8(0)
   660  	}
   661  
   662  	// The rest of moduledata is zero initialized.
   663  	// When linking an object that does not contain the runtime we are
   664  	// creating the moduledata from scratch and it does not have a
   665  	// compiler-provided size, so read it from the type data.
   666  	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   667  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   668  	moduledata.Grow(moduledata.Size)
   669  
   670  	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   671  	if lastmoduledatap.Type != sym.SDYNIMPORT {
   672  		lastmoduledatap.Type = sym.SNOPTRDATA
   673  		lastmoduledatap.Size = 0 // overwrite existing value
   674  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
   675  	}
   676  }