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