github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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/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 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 == obj.SDYNIMPORT || xo.Type == obj.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&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 && 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 == 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|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 == obj.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 = obj.SRODATA
   311  	t.Attr |= AttrReachable
   312  	nsections := int64(0)
   313  
   314  	for sect := Segtext.Sect; sect != nil; sect = sect.Next {
   315  		if sect.Name == ".text" {
   316  			nsections++
   317  		} else {
   318  			break
   319  		}
   320  	}
   321  	Symgrow(t, nsections*(2*int64(SysArch.IntSize)+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.Sect.Vaddr
   336  	for sect := Segtext.Sect; sect != nil; sect = sect.Next {
   337  		if sect.Name != ".text" {
   338  			break
   339  		}
   340  		off = setuintxx(ctxt, t, off, sect.Vaddr-textbase, int64(SysArch.IntSize))
   341  		off = setuintxx(ctxt, t, off, sect.Length, int64(SysArch.IntSize))
   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", obj.STEXT, 0)
   367  
   368  	ctxt.xdefine("runtime.etext", obj.STEXT, 0)
   369  	ctxt.xdefine("runtime.itablink", obj.SRODATA, 0)
   370  	ctxt.xdefine("runtime.eitablink", obj.SRODATA, 0)
   371  	ctxt.xdefine("runtime.rodata", obj.SRODATA, 0)
   372  	ctxt.xdefine("runtime.erodata", obj.SRODATA, 0)
   373  	ctxt.xdefine("runtime.types", obj.SRODATA, 0)
   374  	ctxt.xdefine("runtime.etypes", obj.SRODATA, 0)
   375  	ctxt.xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
   376  	ctxt.xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
   377  	ctxt.xdefine("runtime.data", obj.SDATA, 0)
   378  	ctxt.xdefine("runtime.edata", obj.SDATA, 0)
   379  	ctxt.xdefine("runtime.bss", obj.SBSS, 0)
   380  	ctxt.xdefine("runtime.ebss", obj.SBSS, 0)
   381  	ctxt.xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0)
   382  	ctxt.xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0)
   383  	ctxt.xdefine("runtime.end", obj.SBSS, 0)
   384  	ctxt.xdefine("runtime.epclntab", obj.SRODATA, 0)
   385  	ctxt.xdefine("runtime.esymtab", obj.SRODATA, 0)
   386  
   387  	// garbage collection symbols
   388  	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
   389  
   390  	s.Type = obj.SRODATA
   391  	s.Size = 0
   392  	s.Attr |= AttrReachable
   393  	ctxt.xdefine("runtime.egcdata", obj.SRODATA, 0)
   394  
   395  	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
   396  	s.Type = obj.SRODATA
   397  	s.Size = 0
   398  	s.Attr |= AttrReachable
   399  	ctxt.xdefine("runtime.egcbss", obj.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 = obj.STYPE
   408  		s.Size = 0
   409  		s.Attr |= AttrReachable
   410  		symtype = s
   411  
   412  		s = ctxt.Syms.Lookup("typerel.*", 0)
   413  
   414  		s.Type = obj.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 = obj.STYPE
   422  		s.Size = 0
   423  		s.Attr |= AttrReachable
   424  		symtype = s
   425  		symtyperel = s
   426  	}
   427  
   428  	groupSym := func(name string, t obj.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.*", obj.SGOSTRING)
   437  		symgofunc   = groupSym("go.func.*", obj.SGOFUNC)
   438  		symgcbits   = groupSym("runtime.gcbits.*", obj.SGCBITS)
   439  	)
   440  
   441  	var symgofuncrel *Symbol
   442  	if !ctxt.DynlinkingGo() {
   443  		if UseRelro() {
   444  			symgofuncrel = groupSym("go.funcrel.*", obj.SGOFUNCRELRO)
   445  		} else {
   446  			symgofuncrel = symgofunc
   447  		}
   448  	}
   449  
   450  	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   451  	symitablink.Type = obj.SITABLINK
   452  
   453  	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   454  	symt.Attr |= AttrLocal
   455  	symt.Type = obj.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 != obj.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 = obj.STYPERELRO
   477  				s.Outer = symtyperel
   478  			} else {
   479  				s.Type = obj.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 = obj.STYPERELRO
   487  
   488  		case strings.HasPrefix(s.Name, "go.itablink."):
   489  			nitablinks++
   490  			s.Type = obj.SITABLINK
   491  			s.Attr |= AttrHidden
   492  			s.Outer = symitablink
   493  
   494  		case strings.HasPrefix(s.Name, "go.string."):
   495  			s.Type = obj.SGOSTRING
   496  			s.Attr |= AttrHidden
   497  			s.Outer = symgostring
   498  
   499  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   500  			s.Type = obj.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 = obj.SGOFUNCRELRO
   510  				s.Outer = symgofuncrel
   511  			} else {
   512  				s.Type = obj.SGOFUNC
   513  				s.Outer = symgofunc
   514  			}
   515  
   516  		case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"):
   517  			s.Type = obj.SGOFUNC
   518  			s.Attr |= AttrHidden
   519  			s.Outer = symgofunc
   520  			s.Align = 4
   521  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   522  		}
   523  	}
   524  
   525  	if Buildmode == BuildmodeShared {
   526  		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   527  		abihashgostr.Attr |= AttrReachable
   528  		abihashgostr.Type = obj.SRODATA
   529  		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   530  		Addaddr(ctxt, abihashgostr, hashsym)
   531  		adduint(ctxt, abihashgostr, uint64(hashsym.Size))
   532  	}
   533  
   534  	nsections := textsectionmap(ctxt)
   535  
   536  	// Information about the layout of the executable image for the
   537  	// runtime to use. Any changes here must be matched by changes to
   538  	// the definition of moduledata in runtime/symtab.go.
   539  	// This code uses several global variables that are set by pcln.go:pclntab.
   540  	moduledata := ctxt.Moduledata
   541  	// The pclntab slice
   542  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0))
   543  	adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   544  	adduint(ctxt, moduledata, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   545  	// The ftab slice
   546  	Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   547  	adduint(ctxt, moduledata, uint64(pclntabNfunc+1))
   548  	adduint(ctxt, moduledata, uint64(pclntabNfunc+1))
   549  	// The filetab slice
   550  	Addaddrplus(ctxt, moduledata, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   551  	adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1)
   552  	adduint(ctxt, moduledata, uint64(len(ctxt.Filesyms))+1)
   553  	// findfunctab
   554  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   555  	// minpc, maxpc
   556  	Addaddr(ctxt, moduledata, pclntabFirstFunc)
   557  	Addaddrplus(ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
   558  	// pointers to specific parts of the module
   559  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.text", 0))
   560  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etext", 0))
   561  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   562  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   563  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.data", 0))
   564  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.edata", 0))
   565  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.bss", 0))
   566  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.ebss", 0))
   567  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   568  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   569  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.end", 0))
   570  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcdata", 0))
   571  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.gcbss", 0))
   572  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.types", 0))
   573  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.etypes", 0))
   574  
   575  	// text section information
   576  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   577  	adduint(ctxt, moduledata, uint64(nsections))
   578  	adduint(ctxt, moduledata, uint64(nsections))
   579  
   580  	// The typelinks slice
   581  	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   582  	ntypelinks := uint64(typelinkSym.Size) / 4
   583  	Addaddr(ctxt, moduledata, typelinkSym)
   584  	adduint(ctxt, moduledata, ntypelinks)
   585  	adduint(ctxt, moduledata, ntypelinks)
   586  	// The itablinks slice
   587  	Addaddr(ctxt, moduledata, ctxt.Syms.Lookup("runtime.itablink", 0))
   588  	adduint(ctxt, moduledata, uint64(nitablinks))
   589  	adduint(ctxt, moduledata, uint64(nitablinks))
   590  	// The ptab slice
   591  	if Buildmode == BuildmodePlugin {
   592  		ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0)
   593  		ptab.Attr |= AttrReachable
   594  		ptab.Attr |= AttrLocal
   595  		ptab.Type = obj.SRODATA
   596  
   597  		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   598  		Addaddr(ctxt, moduledata, ptab)
   599  		adduint(ctxt, moduledata, nentries)
   600  		adduint(ctxt, moduledata, nentries)
   601  	} else {
   602  		adduint(ctxt, moduledata, 0)
   603  		adduint(ctxt, moduledata, 0)
   604  		adduint(ctxt, moduledata, 0)
   605  	}
   606  	if Buildmode == BuildmodePlugin {
   607  		addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath)
   608  	} else {
   609  		adduint(ctxt, moduledata, 0)
   610  		adduint(ctxt, moduledata, 0)
   611  	}
   612  	if len(ctxt.Shlibs) > 0 {
   613  		thismodulename := filepath.Base(*flagOutfile)
   614  		switch Buildmode {
   615  		case BuildmodeExe, BuildmodePIE:
   616  			// When linking an executable, outfile is just "a.out". Make
   617  			// it something slightly more comprehensible.
   618  			thismodulename = "the executable"
   619  		}
   620  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   621  
   622  		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   623  		modulehashes.Attr |= AttrReachable
   624  		modulehashes.Attr |= AttrLocal
   625  		modulehashes.Type = obj.SRODATA
   626  
   627  		for i, shlib := range ctxt.Shlibs {
   628  			// modulehashes[i].modulename
   629  			modulename := filepath.Base(shlib.Path)
   630  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   631  
   632  			// modulehashes[i].linktimehash
   633  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   634  
   635  			// modulehashes[i].runtimehash
   636  			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   637  			abihash.Attr |= AttrReachable
   638  			Addaddr(ctxt, modulehashes, abihash)
   639  		}
   640  
   641  		Addaddr(ctxt, moduledata, modulehashes)
   642  		adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs)))
   643  		adduint(ctxt, moduledata, uint64(len(ctxt.Shlibs)))
   644  	}
   645  
   646  	// The rest of moduledata is zero initialized.
   647  	// When linking an object that does not contain the runtime we are
   648  	// creating the moduledata from scratch and it does not have a
   649  	// compiler-provided size, so read it from the type data.
   650  	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   651  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   652  	Symgrow(moduledata, moduledata.Size)
   653  
   654  	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   655  	if lastmoduledatap.Type != obj.SDYNIMPORT {
   656  		lastmoduledatap.Type = obj.SNOPTRDATA
   657  		lastmoduledatap.Size = 0 // overwrite existing value
   658  		Addaddr(ctxt, lastmoduledatap, moduledata)
   659  	}
   660  }