github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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  	"github.com/gagliardetto/golang-go/cmd/internal/objabi"
    35  	"github.com/gagliardetto/golang-go/cmd/internal/sys"
    36  	"github.com/gagliardetto/golang-go/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 || xo.Type == sym.SUNDEFEXT {
   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  	switch ctxt.BuildMode {
   330  	case BuildModeCArchive, BuildModeCShared:
   331  		for _, s := range ctxt.Syms.Allsym {
   332  			// Create a new entry in the .init_array section that points to the
   333  			// library initializer function.
   334  			if s.Name == *flagEntrySymbol && ctxt.HeadType != objabi.Haix {
   335  				addinitarrdata(ctxt, s)
   336  			}
   337  		}
   338  	}
   339  
   340  	// Define these so that they'll get put into the symbol table.
   341  	// data.c:/^address will provide the actual values.
   342  	ctxt.xdefine("runtime.text", sym.STEXT, 0)
   343  
   344  	ctxt.xdefine("runtime.etext", sym.STEXT, 0)
   345  	ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
   346  	ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
   347  	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
   348  	ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
   349  	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
   350  	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
   351  	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
   352  	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
   353  	ctxt.xdefine("runtime.data", sym.SDATA, 0)
   354  	ctxt.xdefine("runtime.edata", sym.SDATA, 0)
   355  	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
   356  	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
   357  	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
   358  	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
   359  	ctxt.xdefine("runtime.end", sym.SBSS, 0)
   360  	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   361  	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
   362  
   363  	// garbage collection symbols
   364  	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
   365  
   366  	s.Type = sym.SRODATA
   367  	s.Size = 0
   368  	s.Attr |= sym.AttrReachable
   369  	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   370  
   371  	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
   372  	s.Type = sym.SRODATA
   373  	s.Size = 0
   374  	s.Attr |= sym.AttrReachable
   375  	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   376  
   377  	// pseudo-symbols to mark locations of type, string, and go string data.
   378  	var symtype *sym.Symbol
   379  	var symtyperel *sym.Symbol
   380  	if !ctxt.DynlinkingGo() {
   381  		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   382  			s = ctxt.Syms.Lookup("type.*", 0)
   383  
   384  			s.Type = sym.STYPE
   385  			s.Size = 0
   386  			s.Attr |= sym.AttrReachable
   387  			symtype = s
   388  
   389  			s = ctxt.Syms.Lookup("typerel.*", 0)
   390  
   391  			s.Type = sym.STYPERELRO
   392  			s.Size = 0
   393  			s.Attr |= sym.AttrReachable
   394  			symtyperel = s
   395  		} else {
   396  			s = ctxt.Syms.Lookup("type.*", 0)
   397  
   398  			s.Type = sym.STYPE
   399  			s.Size = 0
   400  			s.Attr |= sym.AttrReachable
   401  			symtype = s
   402  			symtyperel = s
   403  		}
   404  	}
   405  
   406  	groupSym := func(name string, t sym.SymKind) *sym.Symbol {
   407  		s := ctxt.Syms.Lookup(name, 0)
   408  		s.Type = t
   409  		s.Size = 0
   410  		s.Attr |= sym.AttrLocal | sym.AttrReachable
   411  		return s
   412  	}
   413  	var (
   414  		symgostring = groupSym("go.string.*", sym.SGOSTRING)
   415  		symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
   416  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   417  	)
   418  
   419  	var symgofuncrel *sym.Symbol
   420  	if !ctxt.DynlinkingGo() {
   421  		if ctxt.UseRelro() {
   422  			symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
   423  		} else {
   424  			symgofuncrel = symgofunc
   425  		}
   426  	}
   427  
   428  	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   429  	symitablink.Type = sym.SITABLINK
   430  
   431  	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   432  	symt.Attr |= sym.AttrLocal
   433  	symt.Type = sym.SSYMTAB
   434  	symt.Size = 0
   435  	symt.Attr |= sym.AttrReachable
   436  
   437  	nitablinks := 0
   438  
   439  	// assign specific types so that they sort together.
   440  	// within a type they sort by size, so the .* symbols
   441  	// just defined above will be first.
   442  	// hide the specific symbols.
   443  	for _, s := range ctxt.Syms.Allsym {
   444  		if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
   445  			s.Attr |= sym.AttrNotInSymbolTable
   446  		}
   447  
   448  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
   449  			continue
   450  		}
   451  
   452  		switch {
   453  		case strings.HasPrefix(s.Name, "type."):
   454  			if !ctxt.DynlinkingGo() {
   455  				s.Attr |= sym.AttrNotInSymbolTable
   456  			}
   457  			if ctxt.UseRelro() {
   458  				s.Type = sym.STYPERELRO
   459  				s.Outer = symtyperel
   460  			} else {
   461  				s.Type = sym.STYPE
   462  				s.Outer = symtype
   463  			}
   464  
   465  		case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro():
   466  			// Keep go.importpath symbols in the same section as types and
   467  			// names, as they can be referred to by a section offset.
   468  			s.Type = sym.STYPERELRO
   469  
   470  		case strings.HasPrefix(s.Name, "go.itablink."):
   471  			nitablinks++
   472  			s.Type = sym.SITABLINK
   473  			s.Attr |= sym.AttrNotInSymbolTable
   474  			s.Outer = symitablink
   475  
   476  		case strings.HasPrefix(s.Name, "go.string."):
   477  			s.Type = sym.SGOSTRING
   478  			s.Attr |= sym.AttrNotInSymbolTable
   479  			s.Outer = symgostring
   480  
   481  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   482  			s.Type = sym.SGCBITS
   483  			s.Attr |= sym.AttrNotInSymbolTable
   484  			s.Outer = symgcbits
   485  
   486  		case strings.HasSuffix(s.Name, "·f"):
   487  			if !ctxt.DynlinkingGo() {
   488  				s.Attr |= sym.AttrNotInSymbolTable
   489  			}
   490  			if ctxt.UseRelro() {
   491  				s.Type = sym.SGOFUNCRELRO
   492  				s.Outer = symgofuncrel
   493  			} else {
   494  				s.Type = sym.SGOFUNC
   495  				s.Outer = symgofunc
   496  			}
   497  
   498  		case strings.HasPrefix(s.Name, "gcargs."),
   499  			strings.HasPrefix(s.Name, "gclocals."),
   500  			strings.HasPrefix(s.Name, "gclocals·"),
   501  			strings.HasPrefix(s.Name, "inltree."),
   502  			strings.HasSuffix(s.Name, ".opendefer"):
   503  			s.Type = sym.SGOFUNC
   504  			s.Attr |= sym.AttrNotInSymbolTable
   505  			s.Outer = symgofunc
   506  			s.Align = 4
   507  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   508  		}
   509  	}
   510  
   511  	if ctxt.BuildMode == BuildModeShared {
   512  		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   513  		abihashgostr.Attr |= sym.AttrReachable
   514  		abihashgostr.Type = sym.SRODATA
   515  		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   516  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   517  		abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
   518  	}
   519  	if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   520  		for _, l := range ctxt.Library {
   521  			s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
   522  			s.Attr |= sym.AttrReachable
   523  			s.Type = sym.SRODATA
   524  			s.Size = int64(len(l.Hash))
   525  			s.P = []byte(l.Hash)
   526  			str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
   527  			str.Attr |= sym.AttrReachable
   528  			str.Type = sym.SRODATA
   529  			str.AddAddr(ctxt.Arch, s)
   530  			str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
   531  		}
   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  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
   543  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   544  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   545  	// The ftab slice
   546  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   547  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   548  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   549  	// The filetab slice
   550  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   551  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   552  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   553  	// findfunctab
   554  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   555  	// minpc, maxpc
   556  	moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
   557  	moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size)
   558  	// pointers to specific parts of the module
   559  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
   560  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
   561  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   562  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   563  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
   564  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
   565  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
   566  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
   567  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   568  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   569  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
   570  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
   571  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
   572  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
   573  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
   574  
   575  	if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
   576  		// Add R_REF relocation to prevent ld's garbage collection of
   577  		// runtime.rodata, runtime.erodata and runtime.epclntab.
   578  		addRef := func(name string) {
   579  			r := moduledata.AddRel()
   580  			r.Sym = ctxt.Syms.Lookup(name, 0)
   581  			r.Type = objabi.R_XCOFFREF
   582  			r.Siz = uint8(ctxt.Arch.PtrSize)
   583  		}
   584  		addRef("runtime.rodata")
   585  		addRef("runtime.erodata")
   586  		addRef("runtime.epclntab")
   587  	}
   588  
   589  	// text section information
   590  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   591  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   592  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   593  
   594  	// The typelinks slice
   595  	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   596  	ntypelinks := uint64(typelinkSym.Size) / 4
   597  	moduledata.AddAddr(ctxt.Arch, typelinkSym)
   598  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   599  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   600  	// The itablinks slice
   601  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0))
   602  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   603  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   604  	// The ptab slice
   605  	if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
   606  		ptab.Attr |= sym.AttrLocal
   607  		ptab.Type = sym.SRODATA
   608  
   609  		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   610  		moduledata.AddAddr(ctxt.Arch, ptab)
   611  		moduledata.AddUint(ctxt.Arch, nentries)
   612  		moduledata.AddUint(ctxt.Arch, nentries)
   613  	} else {
   614  		moduledata.AddUint(ctxt.Arch, 0)
   615  		moduledata.AddUint(ctxt.Arch, 0)
   616  		moduledata.AddUint(ctxt.Arch, 0)
   617  	}
   618  	if ctxt.BuildMode == BuildModePlugin {
   619  		addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   620  
   621  		pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
   622  		pkghashes.Attr |= sym.AttrReachable
   623  		pkghashes.Attr |= sym.AttrLocal
   624  		pkghashes.Type = sym.SRODATA
   625  
   626  		for i, l := range ctxt.Library {
   627  			// pkghashes[i].name
   628  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   629  			// pkghashes[i].linktimehash
   630  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
   631  			// pkghashes[i].runtimehash
   632  			hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
   633  			pkghashes.AddAddr(ctxt.Arch, hash)
   634  		}
   635  		moduledata.AddAddr(ctxt.Arch, pkghashes)
   636  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   637  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   638  	} else {
   639  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   640  		moduledata.AddUint(ctxt.Arch, 0)
   641  		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   642  		moduledata.AddUint(ctxt.Arch, 0)
   643  		moduledata.AddUint(ctxt.Arch, 0)
   644  	}
   645  	if len(ctxt.Shlibs) > 0 {
   646  		thismodulename := filepath.Base(*flagOutfile)
   647  		switch ctxt.BuildMode {
   648  		case BuildModeExe, BuildModePIE:
   649  			// When linking an executable, outfile is just "a.out". Make
   650  			// it something slightly more comprehensible.
   651  			thismodulename = "the executable"
   652  		}
   653  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   654  
   655  		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   656  		modulehashes.Attr |= sym.AttrReachable
   657  		modulehashes.Attr |= sym.AttrLocal
   658  		modulehashes.Type = sym.SRODATA
   659  
   660  		for i, shlib := range ctxt.Shlibs {
   661  			// modulehashes[i].modulename
   662  			modulename := filepath.Base(shlib.Path)
   663  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   664  
   665  			// modulehashes[i].linktimehash
   666  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   667  
   668  			// modulehashes[i].runtimehash
   669  			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   670  			abihash.Attr |= sym.AttrReachable
   671  			modulehashes.AddAddr(ctxt.Arch, abihash)
   672  		}
   673  
   674  		moduledata.AddAddr(ctxt.Arch, modulehashes)
   675  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   676  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   677  	} else {
   678  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   679  		moduledata.AddUint(ctxt.Arch, 0)
   680  		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   681  		moduledata.AddUint(ctxt.Arch, 0)
   682  		moduledata.AddUint(ctxt.Arch, 0)
   683  	}
   684  
   685  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   686  	if hasmain {
   687  		moduledata.AddUint8(1)
   688  	} else {
   689  		moduledata.AddUint8(0)
   690  	}
   691  
   692  	// The rest of moduledata is zero initialized.
   693  	// When linking an object that does not contain the runtime we are
   694  	// creating the moduledata from scratch and it does not have a
   695  	// compiler-provided size, so read it from the type data.
   696  	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   697  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype.P)
   698  	moduledata.Grow(moduledata.Size)
   699  
   700  	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   701  	if lastmoduledatap.Type != sym.SDYNIMPORT {
   702  		lastmoduledatap.Type = sym.SNOPTRDATA
   703  		lastmoduledatap.Size = 0 // overwrite existing value
   704  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
   705  	}
   706  }
   707  
   708  func isStaticTemp(name string) bool {
   709  	if i := strings.LastIndex(name, "/"); i >= 0 {
   710  		name = name[i:]
   711  	}
   712  	return strings.Contains(name, "..stmp_")
   713  }