github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/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.IsFileLocal() || 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.IsFileLocal() {
   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.DynlinkingGo() {
   372  		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   373  			s = ctxt.Syms.Lookup("type.*", 0)
   374  
   375  			s.Type = sym.STYPE
   376  			s.Size = 0
   377  			s.Attr |= sym.AttrReachable
   378  			symtype = s
   379  
   380  			s = ctxt.Syms.Lookup("typerel.*", 0)
   381  
   382  			s.Type = sym.STYPERELRO
   383  			s.Size = 0
   384  			s.Attr |= sym.AttrReachable
   385  			symtyperel = s
   386  		} else {
   387  			s = ctxt.Syms.Lookup("type.*", 0)
   388  
   389  			s.Type = sym.STYPE
   390  			s.Size = 0
   391  			s.Attr |= sym.AttrReachable
   392  			symtype = s
   393  			symtyperel = s
   394  		}
   395  	}
   396  
   397  	groupSym := func(name string, t sym.SymKind) *sym.Symbol {
   398  		s := ctxt.Syms.Lookup(name, 0)
   399  		s.Type = t
   400  		s.Size = 0
   401  		s.Attr |= sym.AttrLocal | sym.AttrReachable
   402  		return s
   403  	}
   404  	var (
   405  		symgostring = groupSym("go.string.*", sym.SGOSTRING)
   406  		symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
   407  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   408  	)
   409  
   410  	var symgofuncrel *sym.Symbol
   411  	if !ctxt.DynlinkingGo() {
   412  		if ctxt.UseRelro() {
   413  			symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
   414  		} else {
   415  			symgofuncrel = symgofunc
   416  		}
   417  	}
   418  
   419  	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   420  	symitablink.Type = sym.SITABLINK
   421  
   422  	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   423  	symt.Attr |= sym.AttrLocal
   424  	symt.Type = sym.SSYMTAB
   425  	symt.Size = 0
   426  	symt.Attr |= sym.AttrReachable
   427  
   428  	nitablinks := 0
   429  
   430  	// assign specific types so that they sort together.
   431  	// within a type they sort by size, so the .* symbols
   432  	// just defined above will be first.
   433  	// hide the specific symbols.
   434  	for _, s := range ctxt.Syms.Allsym {
   435  		if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
   436  			s.Attr |= sym.AttrNotInSymbolTable
   437  		}
   438  
   439  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
   440  			continue
   441  		}
   442  
   443  		switch {
   444  		case strings.HasPrefix(s.Name, "type."):
   445  			if !ctxt.DynlinkingGo() {
   446  				s.Attr |= sym.AttrNotInSymbolTable
   447  			}
   448  			if ctxt.UseRelro() {
   449  				s.Type = sym.STYPERELRO
   450  				s.Outer = symtyperel
   451  			} else {
   452  				s.Type = sym.STYPE
   453  				s.Outer = symtype
   454  			}
   455  
   456  		case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro():
   457  			// Keep go.importpath symbols in the same section as types and
   458  			// names, as they can be referred to by a section offset.
   459  			s.Type = sym.STYPERELRO
   460  
   461  		case strings.HasPrefix(s.Name, "go.itablink."):
   462  			nitablinks++
   463  			s.Type = sym.SITABLINK
   464  			s.Attr |= sym.AttrNotInSymbolTable
   465  			s.Outer = symitablink
   466  
   467  		case strings.HasPrefix(s.Name, "go.string."):
   468  			s.Type = sym.SGOSTRING
   469  			s.Attr |= sym.AttrNotInSymbolTable
   470  			s.Outer = symgostring
   471  
   472  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   473  			s.Type = sym.SGCBITS
   474  			s.Attr |= sym.AttrNotInSymbolTable
   475  			s.Outer = symgcbits
   476  
   477  		case strings.HasSuffix(s.Name, "·f"):
   478  			if !ctxt.DynlinkingGo() {
   479  				s.Attr |= sym.AttrNotInSymbolTable
   480  			}
   481  			if ctxt.UseRelro() {
   482  				s.Type = sym.SGOFUNCRELRO
   483  				s.Outer = symgofuncrel
   484  			} else {
   485  				s.Type = sym.SGOFUNC
   486  				s.Outer = symgofunc
   487  			}
   488  
   489  		case strings.HasPrefix(s.Name, "gcargs."),
   490  			strings.HasPrefix(s.Name, "gclocals."),
   491  			strings.HasPrefix(s.Name, "gclocals·"),
   492  			strings.HasPrefix(s.Name, "inltree."):
   493  			s.Type = sym.SGOFUNC
   494  			s.Attr |= sym.AttrNotInSymbolTable
   495  			s.Outer = symgofunc
   496  			s.Align = 4
   497  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   498  		}
   499  	}
   500  
   501  	if ctxt.BuildMode == BuildModeShared {
   502  		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   503  		abihashgostr.Attr |= sym.AttrReachable
   504  		abihashgostr.Type = sym.SRODATA
   505  		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   506  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   507  		abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
   508  	}
   509  	if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   510  		for _, l := range ctxt.Library {
   511  			s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
   512  			s.Attr |= sym.AttrReachable
   513  			s.Type = sym.SRODATA
   514  			s.Size = int64(len(l.Hash))
   515  			s.P = []byte(l.Hash)
   516  			str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
   517  			str.Attr |= sym.AttrReachable
   518  			str.Type = sym.SRODATA
   519  			str.AddAddr(ctxt.Arch, s)
   520  			str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
   521  		}
   522  	}
   523  
   524  	nsections := textsectionmap(ctxt)
   525  
   526  	// Information about the layout of the executable image for the
   527  	// runtime to use. Any changes here must be matched by changes to
   528  	// the definition of moduledata in runtime/symtab.go.
   529  	// This code uses several global variables that are set by pcln.go:pclntab.
   530  	moduledata := ctxt.Moduledata
   531  	// The pclntab slice
   532  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
   533  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   534  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   535  	// The ftab slice
   536  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   537  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   538  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   539  	// The filetab slice
   540  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   541  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   542  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   543  	// findfunctab
   544  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   545  	// minpc, maxpc
   546  	moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
   547  	moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size)
   548  	// pointers to specific parts of the module
   549  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
   550  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
   551  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   552  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   553  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
   554  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
   555  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
   556  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
   557  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   558  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   559  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
   560  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
   561  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
   562  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
   563  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
   564  
   565  	// text section information
   566  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   567  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   568  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   569  
   570  	// The typelinks slice
   571  	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   572  	ntypelinks := uint64(typelinkSym.Size) / 4
   573  	moduledata.AddAddr(ctxt.Arch, typelinkSym)
   574  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   575  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   576  	// The itablinks slice
   577  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0))
   578  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   579  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   580  	// The ptab slice
   581  	if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
   582  		ptab.Attr |= sym.AttrLocal
   583  		ptab.Type = sym.SRODATA
   584  
   585  		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   586  		moduledata.AddAddr(ctxt.Arch, ptab)
   587  		moduledata.AddUint(ctxt.Arch, nentries)
   588  		moduledata.AddUint(ctxt.Arch, nentries)
   589  	} else {
   590  		moduledata.AddUint(ctxt.Arch, 0)
   591  		moduledata.AddUint(ctxt.Arch, 0)
   592  		moduledata.AddUint(ctxt.Arch, 0)
   593  	}
   594  	if ctxt.BuildMode == BuildModePlugin {
   595  		addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   596  
   597  		pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
   598  		pkghashes.Attr |= sym.AttrReachable
   599  		pkghashes.Attr |= sym.AttrLocal
   600  		pkghashes.Type = sym.SRODATA
   601  
   602  		for i, l := range ctxt.Library {
   603  			// pkghashes[i].name
   604  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   605  			// pkghashes[i].linktimehash
   606  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
   607  			// pkghashes[i].runtimehash
   608  			hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
   609  			pkghashes.AddAddr(ctxt.Arch, hash)
   610  		}
   611  		moduledata.AddAddr(ctxt.Arch, pkghashes)
   612  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   613  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   614  	} else {
   615  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   616  		moduledata.AddUint(ctxt.Arch, 0)
   617  		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   618  		moduledata.AddUint(ctxt.Arch, 0)
   619  		moduledata.AddUint(ctxt.Arch, 0)
   620  	}
   621  	if len(ctxt.Shlibs) > 0 {
   622  		thismodulename := filepath.Base(*flagOutfile)
   623  		switch ctxt.BuildMode {
   624  		case BuildModeExe, BuildModePIE:
   625  			// When linking an executable, outfile is just "a.out". Make
   626  			// it something slightly more comprehensible.
   627  			thismodulename = "the executable"
   628  		}
   629  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   630  
   631  		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   632  		modulehashes.Attr |= sym.AttrReachable
   633  		modulehashes.Attr |= sym.AttrLocal
   634  		modulehashes.Type = sym.SRODATA
   635  
   636  		for i, shlib := range ctxt.Shlibs {
   637  			// modulehashes[i].modulename
   638  			modulename := filepath.Base(shlib.Path)
   639  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   640  
   641  			// modulehashes[i].linktimehash
   642  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   643  
   644  			// modulehashes[i].runtimehash
   645  			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   646  			abihash.Attr |= sym.AttrReachable
   647  			modulehashes.AddAddr(ctxt.Arch, abihash)
   648  		}
   649  
   650  		moduledata.AddAddr(ctxt.Arch, modulehashes)
   651  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   652  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   653  	} else {
   654  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   655  		moduledata.AddUint(ctxt.Arch, 0)
   656  		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   657  		moduledata.AddUint(ctxt.Arch, 0)
   658  		moduledata.AddUint(ctxt.Arch, 0)
   659  	}
   660  
   661  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   662  	if hasmain {
   663  		moduledata.AddUint8(1)
   664  	} else {
   665  		moduledata.AddUint8(0)
   666  	}
   667  
   668  	// The rest of moduledata is zero initialized.
   669  	// When linking an object that does not contain the runtime we are
   670  	// creating the moduledata from scratch and it does not have a
   671  	// compiler-provided size, so read it from the type data.
   672  	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   673  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   674  	moduledata.Grow(moduledata.Size)
   675  
   676  	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   677  	if lastmoduledatap.Type != sym.SDYNIMPORT {
   678  		lastmoduledatap.Type = sym.SNOPTRDATA
   679  		lastmoduledatap.Size = 0 // overwrite existing value
   680  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
   681  	}
   682  }
   683  
   684  func isStaticTemp(name string) bool {
   685  	if i := strings.LastIndex(name, "/"); i >= 0 {
   686  		name = name[i:]
   687  	}
   688  	return strings.Contains(name, "..stmp_")
   689  }