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