github.com/bir3/gocompiler@v0.3.205/src/cmd/link/internal/ld/symtab.go (about)

     1  // Inferno utils/6l/span.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/master/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/bir3/gocompiler/src/cmd/internal/obj"
    35  	"github.com/bir3/gocompiler/src/cmd/internal/objabi"
    36  	"github.com/bir3/gocompiler/src/cmd/link/internal/loader"
    37  	"github.com/bir3/gocompiler/src/cmd/link/internal/sym"
    38  	"debug/elf"
    39  	"fmt"
    40  	"github.com/bir3/gocompiler/src/internal/buildcfg"
    41  	"path/filepath"
    42  	"strings"
    43  )
    44  
    45  // Symbol table.
    46  
    47  func putelfstr(s string) int {
    48  	if len(Elfstrdat) == 0 && s != "" {
    49  		// first entry must be empty string
    50  		putelfstr("")
    51  	}
    52  
    53  	off := len(Elfstrdat)
    54  	Elfstrdat = append(Elfstrdat, s...)
    55  	Elfstrdat = append(Elfstrdat, 0)
    56  	return off
    57  }
    58  
    59  func putelfsyment(out *OutBuf, off int, addr int64, size int64, info uint8, shndx elf.SectionIndex, other int) {
    60  	if elf64 {
    61  		out.Write32(uint32(off))
    62  		out.Write8(info)
    63  		out.Write8(uint8(other))
    64  		out.Write16(uint16(shndx))
    65  		out.Write64(uint64(addr))
    66  		out.Write64(uint64(size))
    67  		symSize += ELF64SYMSIZE
    68  	} else {
    69  		out.Write32(uint32(off))
    70  		out.Write32(uint32(addr))
    71  		out.Write32(uint32(size))
    72  		out.Write8(info)
    73  		out.Write8(uint8(other))
    74  		out.Write16(uint16(shndx))
    75  		symSize += ELF32SYMSIZE
    76  	}
    77  }
    78  
    79  func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) {
    80  	ldr := ctxt.loader
    81  	addr := ldr.SymValue(x)
    82  	size := ldr.SymSize(x)
    83  
    84  	xo := x
    85  	if ldr.OuterSym(x) != 0 {
    86  		xo = ldr.OuterSym(x)
    87  	}
    88  	xot := ldr.SymType(xo)
    89  	xosect := ldr.SymSect(xo)
    90  
    91  	var elfshnum elf.SectionIndex
    92  	if xot == sym.SDYNIMPORT || xot == sym.SHOSTOBJ || xot == sym.SUNDEFEXT {
    93  		elfshnum = elf.SHN_UNDEF
    94  		size = 0
    95  	} else {
    96  		if xosect == nil {
    97  			ldr.Errorf(x, "missing section in putelfsym")
    98  			return
    99  		}
   100  		if xosect.Elfsect == nil {
   101  			ldr.Errorf(x, "missing ELF section in putelfsym")
   102  			return
   103  		}
   104  		elfshnum = xosect.Elfsect.(*ElfShdr).shnum
   105  	}
   106  
   107  	sname := ldr.SymExtname(x)
   108  	sname = mangleABIName(ctxt, ldr, x, sname)
   109  
   110  	// One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL,
   111  	// maybe one day elf.STB_WEAK.
   112  	bind := elf.STB_GLOBAL
   113  	if ldr.IsFileLocal(x) && !isStaticTmp(sname) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
   114  		// Static tmp is package local, but a package can be shared among multiple DSOs.
   115  		// They need to have a single view of the static tmp that are writable.
   116  		bind = elf.STB_LOCAL
   117  	}
   118  
   119  	// In external linking mode, we have to invoke gcc with -rdynamic
   120  	// to get the exported symbols put into the dynamic symbol table.
   121  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   122  	// mark all Go symbols local (not global) in the final executable.
   123  	// But when we're dynamically linking, we need all those global symbols.
   124  	if !ctxt.DynlinkingGo() && ctxt.IsExternal() && !ldr.AttrCgoExportStatic(x) && elfshnum != elf.SHN_UNDEF {
   125  		bind = elf.STB_LOCAL
   126  	}
   127  
   128  	if ctxt.LinkMode == LinkExternal && elfshnum != elf.SHN_UNDEF {
   129  		addr -= int64(xosect.Vaddr)
   130  	}
   131  	other := int(elf.STV_DEFAULT)
   132  	if ldr.AttrVisibilityHidden(x) {
   133  		// TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when
   134  		// internally linking. But STV_HIDDEN visibility only matters in object
   135  		// files and shared libraries, and as we are a long way from implementing
   136  		// internal linking for shared libraries and only create object files when
   137  		// externally linking, I don't think this makes a lot of sense.
   138  		other = int(elf.STV_HIDDEN)
   139  	}
   140  	if ctxt.IsPPC64() && typ == elf.STT_FUNC && ldr.AttrShared(x) && ldr.SymName(x) != "runtime.duffzero" && ldr.SymName(x) != "runtime.duffcopy" {
   141  		// On ppc64 the top three bits of the st_other field indicate how
   142  		// many instructions separate the global and local entry points. In
   143  		// our case it is two instructions, indicated by the value 3.
   144  		// The conditions here match those in preprocess in
   145  		// cmd/internal/obj/ppc64/obj9.go, which is where the
   146  		// instructions are inserted.
   147  		other |= 3 << 5
   148  	}
   149  
   150  	// When dynamically linking, we create Symbols by reading the names from
   151  	// the symbol tables of the shared libraries and so the names need to
   152  	// match exactly. Tools like DTrace will have to wait for now.
   153  	if !ctxt.DynlinkingGo() {
   154  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
   155  		sname = strings.Replace(sname, "·", ".", -1)
   156  	}
   157  
   158  	if ctxt.DynlinkingGo() && bind == elf.STB_GLOBAL && curbind == elf.STB_LOCAL && ldr.SymType(x) == sym.STEXT {
   159  		// When dynamically linking, we want references to functions defined
   160  		// in this module to always be to the function object, not to the
   161  		// PLT. We force this by writing an additional local symbol for every
   162  		// global function symbol and making all relocations against the
   163  		// global symbol refer to this local symbol instead (see
   164  		// (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the
   165  		// ELF linker -Bsymbolic-functions option, but that is buggy on
   166  		// several platforms.
   167  		putelfsyment(ctxt.Out, putelfstr("local."+sname), addr, size, elf.ST_INFO(elf.STB_LOCAL, typ), elfshnum, other)
   168  		ldr.SetSymLocalElfSym(x, int32(ctxt.numelfsym))
   169  		ctxt.numelfsym++
   170  		return
   171  	} else if bind != curbind {
   172  		return
   173  	}
   174  
   175  	putelfsyment(ctxt.Out, putelfstr(sname), addr, size, elf.ST_INFO(bind, typ), elfshnum, other)
   176  	ldr.SetSymElfSym(x, int32(ctxt.numelfsym))
   177  	ctxt.numelfsym++
   178  }
   179  
   180  func putelfsectionsym(ctxt *Link, out *OutBuf, s loader.Sym, shndx elf.SectionIndex) {
   181  	putelfsyment(out, 0, 0, 0, elf.ST_INFO(elf.STB_LOCAL, elf.STT_SECTION), shndx, 0)
   182  	ctxt.loader.SetSymElfSym(s, int32(ctxt.numelfsym))
   183  	ctxt.numelfsym++
   184  }
   185  
   186  func genelfsym(ctxt *Link, elfbind elf.SymBind) {
   187  	ldr := ctxt.loader
   188  
   189  	// runtime.text marker symbol(s).
   190  	s := ldr.Lookup("runtime.text", 0)
   191  	putelfsym(ctxt, s, elf.STT_FUNC, elfbind)
   192  	for k, sect := range Segtext.Sections[1:] {
   193  		n := k + 1
   194  		if sect.Name != ".text" || (ctxt.IsAIX() && ctxt.IsExternal()) {
   195  			// On AIX, runtime.text.X are symbols already in the symtab.
   196  			break
   197  		}
   198  		s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
   199  		if s == 0 {
   200  			break
   201  		}
   202  		if ldr.SymType(s) != sym.STEXT {
   203  			panic("unexpected type for runtime.text symbol")
   204  		}
   205  		putelfsym(ctxt, s, elf.STT_FUNC, elfbind)
   206  	}
   207  
   208  	// Text symbols.
   209  	for _, s := range ctxt.Textp {
   210  		putelfsym(ctxt, s, elf.STT_FUNC, elfbind)
   211  	}
   212  
   213  	// runtime.etext marker symbol.
   214  	s = ldr.Lookup("runtime.etext", 0)
   215  	if ldr.SymType(s) == sym.STEXT {
   216  		putelfsym(ctxt, s, elf.STT_FUNC, elfbind)
   217  	}
   218  
   219  	shouldBeInSymbolTable := func(s loader.Sym) bool {
   220  		if ldr.AttrNotInSymbolTable(s) {
   221  			return false
   222  		}
   223  		// FIXME: avoid having to do name inspections here.
   224  		// NB: the restrictions below on file local symbols are a bit
   225  		// arbitrary -- if it turns out we need nameless static
   226  		// symbols they could be relaxed/removed.
   227  		sn := ldr.SymName(s)
   228  		if (sn == "" || sn[0] == '.') && ldr.IsFileLocal(s) {
   229  			panic(fmt.Sprintf("unexpected file local symbol %d %s<%d>\n",
   230  				s, sn, ldr.SymVersion(s)))
   231  		}
   232  		if (sn == "" || sn[0] == '.') && !ldr.IsFileLocal(s) {
   233  			return false
   234  		}
   235  		return true
   236  	}
   237  
   238  	// Data symbols.
   239  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   240  		if !ldr.AttrReachable(s) {
   241  			continue
   242  		}
   243  		st := ldr.SymType(s)
   244  		if st >= sym.SELFRXSECT && st < sym.SXREF {
   245  			typ := elf.STT_OBJECT
   246  			if st == sym.STLSBSS {
   247  				if ctxt.IsInternal() {
   248  					continue
   249  				}
   250  				typ = elf.STT_TLS
   251  			}
   252  			if !shouldBeInSymbolTable(s) {
   253  				continue
   254  			}
   255  			putelfsym(ctxt, s, typ, elfbind)
   256  			continue
   257  		}
   258  		if st == sym.SHOSTOBJ || st == sym.SDYNIMPORT || st == sym.SUNDEFEXT {
   259  			putelfsym(ctxt, s, ldr.SymElfType(s), elfbind)
   260  		}
   261  	}
   262  }
   263  
   264  func asmElfSym(ctxt *Link) {
   265  
   266  	// the first symbol entry is reserved
   267  	putelfsyment(ctxt.Out, 0, 0, 0, elf.ST_INFO(elf.STB_LOCAL, elf.STT_NOTYPE), 0, 0)
   268  
   269  	dwarfaddelfsectionsyms(ctxt)
   270  
   271  	// Some linkers will add a FILE sym if one is not present.
   272  	// Avoid having the working directory inserted into the symbol table.
   273  	// It is added with a name to avoid problems with external linking
   274  	// encountered on some versions of Solaris. See issue #14957.
   275  	putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, elf.ST_INFO(elf.STB_LOCAL, elf.STT_FILE), elf.SHN_ABS, 0)
   276  	ctxt.numelfsym++
   277  
   278  	bindings := []elf.SymBind{elf.STB_LOCAL, elf.STB_GLOBAL}
   279  	for _, elfbind := range bindings {
   280  		if elfbind == elf.STB_GLOBAL {
   281  			elfglobalsymndx = ctxt.numelfsym
   282  		}
   283  		genelfsym(ctxt, elfbind)
   284  	}
   285  }
   286  
   287  func putplan9sym(ctxt *Link, ldr *loader.Loader, s loader.Sym, char SymbolType) {
   288  	t := int(char)
   289  	if ldr.IsFileLocal(s) {
   290  		t += 'a' - 'A'
   291  	}
   292  	l := 4
   293  	addr := ldr.SymValue(s)
   294  	if ctxt.IsAMD64() && !flag8 {
   295  		ctxt.Out.Write32b(uint32(addr >> 32))
   296  		l = 8
   297  	}
   298  
   299  	ctxt.Out.Write32b(uint32(addr))
   300  	ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */
   301  
   302  	name := ldr.SymName(s)
   303  	name = mangleABIName(ctxt, ldr, s, name)
   304  	ctxt.Out.WriteString(name)
   305  	ctxt.Out.Write8(0)
   306  
   307  	symSize += int32(l) + 1 + int32(len(name)) + 1
   308  }
   309  
   310  func asmbPlan9Sym(ctxt *Link) {
   311  	ldr := ctxt.loader
   312  
   313  	// Add special runtime.text and runtime.etext symbols.
   314  	s := ldr.Lookup("runtime.text", 0)
   315  	if ldr.SymType(s) == sym.STEXT {
   316  		putplan9sym(ctxt, ldr, s, TextSym)
   317  	}
   318  	s = ldr.Lookup("runtime.etext", 0)
   319  	if ldr.SymType(s) == sym.STEXT {
   320  		putplan9sym(ctxt, ldr, s, TextSym)
   321  	}
   322  
   323  	// Add text symbols.
   324  	for _, s := range ctxt.Textp {
   325  		putplan9sym(ctxt, ldr, s, TextSym)
   326  	}
   327  
   328  	shouldBeInSymbolTable := func(s loader.Sym) bool {
   329  		if ldr.AttrNotInSymbolTable(s) {
   330  			return false
   331  		}
   332  		name := ldr.SymName(s) // TODO: try not to read the name
   333  		if name == "" || name[0] == '.' {
   334  			return false
   335  		}
   336  		return true
   337  	}
   338  
   339  	// Add data symbols and external references.
   340  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   341  		if !ldr.AttrReachable(s) {
   342  			continue
   343  		}
   344  		t := ldr.SymType(s)
   345  		if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
   346  			if t == sym.STLSBSS {
   347  				continue
   348  			}
   349  			if !shouldBeInSymbolTable(s) {
   350  				continue
   351  			}
   352  			char := DataSym
   353  			if t == sym.SBSS || t == sym.SNOPTRBSS {
   354  				char = BSSSym
   355  			}
   356  			putplan9sym(ctxt, ldr, s, char)
   357  		}
   358  	}
   359  }
   360  
   361  type byPkg []*sym.Library
   362  
   363  func (libs byPkg) Len() int {
   364  	return len(libs)
   365  }
   366  
   367  func (libs byPkg) Less(a, b int) bool {
   368  	return libs[a].Pkg < libs[b].Pkg
   369  }
   370  
   371  func (libs byPkg) Swap(a, b int) {
   372  	libs[a], libs[b] = libs[b], libs[a]
   373  }
   374  
   375  // Create a table with information on the text sections.
   376  // Return the symbol of the table, and number of sections.
   377  func textsectionmap(ctxt *Link) (loader.Sym, uint32) {
   378  	ldr := ctxt.loader
   379  	t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0)
   380  	t.SetType(sym.SRODATA)
   381  	nsections := int64(0)
   382  
   383  	for _, sect := range Segtext.Sections {
   384  		if sect.Name == ".text" {
   385  			nsections++
   386  		} else {
   387  			break
   388  		}
   389  	}
   390  	t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize))
   391  
   392  	off := int64(0)
   393  	n := 0
   394  
   395  	// The vaddr for each text section is the difference between the section's
   396  	// Vaddr and the Vaddr for the first text section as determined at compile
   397  	// time.
   398  
   399  	// The symbol for the first text section is named runtime.text as before.
   400  	// Additional text sections are named runtime.text.n where n is the
   401  	// order of creation starting with 1. These symbols provide the section's
   402  	// address after relocation by the linker.
   403  
   404  	textbase := Segtext.Sections[0].Vaddr
   405  	for _, sect := range Segtext.Sections {
   406  		if sect.Name != ".text" {
   407  			break
   408  		}
   409  		// The fields written should match runtime/symtab.go:textsect.
   410  		// They are designed to minimize runtime calculations.
   411  		vaddr := sect.Vaddr - textbase
   412  		off = t.SetUint(ctxt.Arch, off, vaddr) // field vaddr
   413  		end := vaddr + sect.Length
   414  		off = t.SetUint(ctxt.Arch, off, end) // field end
   415  		name := "runtime.text"
   416  		if n != 0 {
   417  			name = fmt.Sprintf("runtime.text.%d", n)
   418  		}
   419  		s := ldr.Lookup(name, 0)
   420  		if s == 0 {
   421  			ctxt.Errorf(s, "Unable to find symbol %s\n", name)
   422  		}
   423  		off = t.SetAddr(ctxt.Arch, off, s) // field baseaddr
   424  		n++
   425  	}
   426  	return t.Sym(), uint32(n)
   427  }
   428  
   429  func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
   430  	ldr := ctxt.loader
   431  
   432  	if !ctxt.IsAIX() {
   433  		switch ctxt.BuildMode {
   434  		case BuildModeCArchive, BuildModeCShared:
   435  			s := ldr.Lookup(*flagEntrySymbol, sym.SymVerABI0)
   436  			if s != 0 {
   437  				addinitarrdata(ctxt, ldr, s)
   438  			}
   439  		}
   440  	}
   441  
   442  	// Define these so that they'll get put into the symbol table.
   443  	// data.c:/^address will provide the actual values.
   444  	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
   445  	ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
   446  	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
   447  	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
   448  	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
   449  	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
   450  	ctxt.xdefine("runtime.data", sym.SDATA, 0)
   451  	ctxt.xdefine("runtime.edata", sym.SDATA, 0)
   452  	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
   453  	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
   454  	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
   455  	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
   456  	ctxt.xdefine("runtime.covctrs", sym.SNOPTRBSS, 0)
   457  	ctxt.xdefine("runtime.ecovctrs", sym.SNOPTRBSS, 0)
   458  	ctxt.xdefine("runtime.end", sym.SBSS, 0)
   459  	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   460  	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
   461  
   462  	// garbage collection symbols
   463  	s := ldr.CreateSymForUpdate("runtime.gcdata", 0)
   464  	s.SetType(sym.SRODATA)
   465  	s.SetSize(0)
   466  	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   467  
   468  	s = ldr.CreateSymForUpdate("runtime.gcbss", 0)
   469  	s.SetType(sym.SRODATA)
   470  	s.SetSize(0)
   471  	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   472  
   473  	// pseudo-symbols to mark locations of type, string, and go string data.
   474  	var symtype, symtyperel loader.Sym
   475  	if !ctxt.DynlinkingGo() {
   476  		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   477  			s = ldr.CreateSymForUpdate("type:*", 0)
   478  			s.SetType(sym.STYPE)
   479  			s.SetSize(0)
   480  			s.SetAlign(int32(ctxt.Arch.PtrSize))
   481  			symtype = s.Sym()
   482  
   483  			s = ldr.CreateSymForUpdate("typerel.*", 0)
   484  			s.SetType(sym.STYPERELRO)
   485  			s.SetSize(0)
   486  			s.SetAlign(int32(ctxt.Arch.PtrSize))
   487  			symtyperel = s.Sym()
   488  		} else {
   489  			s = ldr.CreateSymForUpdate("type:*", 0)
   490  			s.SetType(sym.STYPE)
   491  			s.SetSize(0)
   492  			s.SetAlign(int32(ctxt.Arch.PtrSize))
   493  			symtype = s.Sym()
   494  			symtyperel = s.Sym()
   495  		}
   496  		setCarrierSym(sym.STYPE, symtype)
   497  		setCarrierSym(sym.STYPERELRO, symtyperel)
   498  	}
   499  
   500  	groupSym := func(name string, t sym.SymKind) loader.Sym {
   501  		s := ldr.CreateSymForUpdate(name, 0)
   502  		s.SetType(t)
   503  		s.SetSize(0)
   504  		s.SetAlign(int32(ctxt.Arch.PtrSize))
   505  		s.SetLocal(true)
   506  		setCarrierSym(t, s.Sym())
   507  		return s.Sym()
   508  	}
   509  	var (
   510  		symgostring = groupSym("go:string.*", sym.SGOSTRING)
   511  		symgofunc   = groupSym("go:func.*", sym.SGOFUNC)
   512  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   513  	)
   514  
   515  	symgofuncrel := symgofunc
   516  	if ctxt.UseRelro() {
   517  		symgofuncrel = groupSym("go:funcrel.*", sym.SGOFUNCRELRO)
   518  	}
   519  
   520  	symt := ldr.CreateSymForUpdate("runtime.symtab", 0)
   521  	symt.SetType(sym.SSYMTAB)
   522  	symt.SetSize(0)
   523  	symt.SetLocal(true)
   524  
   525  	// assign specific types so that they sort together.
   526  	// within a type they sort by size, so the .* symbols
   527  	// just defined above will be first.
   528  	// hide the specific symbols.
   529  	// Some of these symbol section conditions are duplicated
   530  	// in cmd/internal/obj.contentHashSection.
   531  	nsym := loader.Sym(ldr.NSym())
   532  	symGroupType := make([]sym.SymKind, nsym)
   533  	for s := loader.Sym(1); s < nsym; s++ {
   534  		if (!ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && ldr.SymPkg(s) != "") || (ctxt.LinkMode == LinkInternal && ldr.SymType(s) == sym.SCOVERAGE_COUNTER) {
   535  			ldr.SetAttrNotInSymbolTable(s, true)
   536  		}
   537  		if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) {
   538  			continue
   539  		}
   540  
   541  		name := ldr.SymName(s)
   542  		switch {
   543  		case strings.HasPrefix(name, "go:string."):
   544  			symGroupType[s] = sym.SGOSTRING
   545  			ldr.SetAttrNotInSymbolTable(s, true)
   546  			ldr.SetCarrierSym(s, symgostring)
   547  
   548  		case strings.HasPrefix(name, "runtime.gcbits."),
   549  			strings.HasPrefix(name, "type:.gcprog."):
   550  			symGroupType[s] = sym.SGCBITS
   551  			ldr.SetAttrNotInSymbolTable(s, true)
   552  			ldr.SetCarrierSym(s, symgcbits)
   553  
   554  		case strings.HasSuffix(name, "·f"):
   555  			if !ctxt.DynlinkingGo() {
   556  				ldr.SetAttrNotInSymbolTable(s, true)
   557  			}
   558  			if ctxt.UseRelro() {
   559  				symGroupType[s] = sym.SGOFUNCRELRO
   560  				if !ctxt.DynlinkingGo() {
   561  					ldr.SetCarrierSym(s, symgofuncrel)
   562  				}
   563  			} else {
   564  				symGroupType[s] = sym.SGOFUNC
   565  				ldr.SetCarrierSym(s, symgofunc)
   566  			}
   567  
   568  		case strings.HasPrefix(name, "gcargs."),
   569  			strings.HasPrefix(name, "gclocals."),
   570  			strings.HasPrefix(name, "gclocals·"),
   571  			ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, // inltree, see pcln.go
   572  			strings.HasSuffix(name, ".opendefer"),
   573  			strings.HasSuffix(name, ".arginfo0"),
   574  			strings.HasSuffix(name, ".arginfo1"),
   575  			strings.HasSuffix(name, ".argliveinfo"),
   576  			strings.HasSuffix(name, ".wrapinfo"),
   577  			strings.HasSuffix(name, ".args_stackmap"),
   578  			strings.HasSuffix(name, ".stkobj"):
   579  			ldr.SetAttrNotInSymbolTable(s, true)
   580  			symGroupType[s] = sym.SGOFUNC
   581  			ldr.SetCarrierSym(s, symgofunc)
   582  			if ctxt.Debugvlog != 0 {
   583  				align := ldr.SymAlign(s)
   584  				liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
   585  			}
   586  
   587  		// Note: Check for "type:" prefix after checking for .arginfo1 suffix.
   588  		// That way symbols like "type:.eq.[2]interface {}.arginfo1" that belong
   589  		// in go:func.* end up there.
   590  		case strings.HasPrefix(name, "type:"):
   591  			if !ctxt.DynlinkingGo() {
   592  				ldr.SetAttrNotInSymbolTable(s, true)
   593  			}
   594  			if ctxt.UseRelro() {
   595  				symGroupType[s] = sym.STYPERELRO
   596  				if symtyperel != 0 {
   597  					ldr.SetCarrierSym(s, symtyperel)
   598  				}
   599  			} else {
   600  				symGroupType[s] = sym.STYPE
   601  				if symtyperel != 0 {
   602  					ldr.SetCarrierSym(s, symtype)
   603  				}
   604  			}
   605  		}
   606  	}
   607  
   608  	if ctxt.BuildMode == BuildModeShared {
   609  		abihashgostr := ldr.CreateSymForUpdate("go:link.abihash."+filepath.Base(*flagOutfile), 0)
   610  		abihashgostr.SetType(sym.SRODATA)
   611  		hashsym := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
   612  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   613  		abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym)))
   614  	}
   615  	if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   616  		for _, l := range ctxt.Library {
   617  			s := ldr.CreateSymForUpdate("go:link.pkghashbytes."+l.Pkg, 0)
   618  			s.SetType(sym.SRODATA)
   619  			s.SetSize(int64(len(l.Fingerprint)))
   620  			s.SetData(l.Fingerprint[:])
   621  			str := ldr.CreateSymForUpdate("go:link.pkghash."+l.Pkg, 0)
   622  			str.SetType(sym.SRODATA)
   623  			str.AddAddr(ctxt.Arch, s.Sym())
   624  			str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint)))
   625  		}
   626  	}
   627  
   628  	textsectionmapSym, nsections := textsectionmap(ctxt)
   629  
   630  	// Information about the layout of the executable image for the
   631  	// runtime to use. Any changes here must be matched by changes to
   632  	// the definition of moduledata in runtime/symtab.go.
   633  	// This code uses several global variables that are set by pcln.go:pclntab.
   634  	moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata)
   635  	// The pcHeader
   636  	moduledata.AddAddr(ctxt.Arch, pcln.pcheader)
   637  	// The function name slice
   638  	moduledata.AddAddr(ctxt.Arch, pcln.funcnametab)
   639  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.funcnametab)))
   640  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.funcnametab)))
   641  	// The cutab slice
   642  	moduledata.AddAddr(ctxt.Arch, pcln.cutab)
   643  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.cutab)))
   644  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.cutab)))
   645  	// The filetab slice
   646  	moduledata.AddAddr(ctxt.Arch, pcln.filetab)
   647  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab)))
   648  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab)))
   649  	// The pctab slice
   650  	moduledata.AddAddr(ctxt.Arch, pcln.pctab)
   651  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab)))
   652  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab)))
   653  	// The pclntab slice
   654  	moduledata.AddAddr(ctxt.Arch, pcln.pclntab)
   655  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab)))
   656  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab)))
   657  	// The ftab slice
   658  	moduledata.AddAddr(ctxt.Arch, pcln.pclntab)
   659  	moduledata.AddUint(ctxt.Arch, uint64(pcln.nfunc+1))
   660  	moduledata.AddUint(ctxt.Arch, uint64(pcln.nfunc+1))
   661  	// findfunctab
   662  	moduledata.AddAddr(ctxt.Arch, pcln.findfunctab)
   663  	// minpc, maxpc
   664  	moduledata.AddAddr(ctxt.Arch, pcln.firstFunc)
   665  	moduledata.AddAddrPlus(ctxt.Arch, pcln.lastFunc, ldr.SymSize(pcln.lastFunc))
   666  	// pointers to specific parts of the module
   667  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0))
   668  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0))
   669  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0))
   670  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0))
   671  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
   672  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0))
   673  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0))
   674  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0))
   675  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0))
   676  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0))
   677  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.covctrs", 0))
   678  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ecovctrs", 0))
   679  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0))
   680  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0))
   681  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
   682  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
   683  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
   684  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0))
   685  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go:func.*", 0))
   686  
   687  	if ctxt.IsAIX() && ctxt.IsExternal() {
   688  		// Add R_XCOFFREF relocation to prevent ld's garbage collection of
   689  		// the following symbols. They might not be referenced in the program.
   690  		addRef := func(name string) {
   691  			s := ldr.Lookup(name, 0)
   692  			if s == 0 {
   693  				return
   694  			}
   695  			r, _ := moduledata.AddRel(objabi.R_XCOFFREF)
   696  			r.SetSym(s)
   697  			r.SetSiz(uint8(ctxt.Arch.PtrSize))
   698  		}
   699  		addRef("runtime.rodata")
   700  		addRef("runtime.erodata")
   701  		addRef("runtime.epclntab")
   702  		// As we use relative addressing for text symbols in functab, it is
   703  		// important that the offsets we computed stay unchanged by the external
   704  		// linker, i.e. all symbols in Textp should not be removed.
   705  		// Most of them are actually referenced (our deadcode pass ensures that),
   706  		// except go:buildid which is generated late and not used by the program.
   707  		addRef("go:buildid")
   708  	}
   709  
   710  	// text section information
   711  	moduledata.AddAddr(ctxt.Arch, textsectionmapSym)
   712  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   713  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   714  
   715  	// The typelinks slice
   716  	typelinkSym := ldr.Lookup("runtime.typelink", 0)
   717  	ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4
   718  	moduledata.AddAddr(ctxt.Arch, typelinkSym)
   719  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   720  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   721  	// The itablinks slice
   722  	itablinkSym := ldr.Lookup("runtime.itablink", 0)
   723  	nitablinks := uint64(ldr.SymSize(itablinkSym)) / uint64(ctxt.Arch.PtrSize)
   724  	moduledata.AddAddr(ctxt.Arch, itablinkSym)
   725  	moduledata.AddUint(ctxt.Arch, nitablinks)
   726  	moduledata.AddUint(ctxt.Arch, nitablinks)
   727  	// The ptab slice
   728  	if ptab := ldr.Lookup("go:plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) {
   729  		ldr.SetAttrLocal(ptab, true)
   730  		if ldr.SymType(ptab) != sym.SRODATA {
   731  			panic(fmt.Sprintf("go:plugin.tabs is %v, not SRODATA", ldr.SymType(ptab)))
   732  		}
   733  		nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff)
   734  		moduledata.AddAddr(ctxt.Arch, ptab)
   735  		moduledata.AddUint(ctxt.Arch, nentries)
   736  		moduledata.AddUint(ctxt.Arch, nentries)
   737  	} else {
   738  		moduledata.AddUint(ctxt.Arch, 0)
   739  		moduledata.AddUint(ctxt.Arch, 0)
   740  		moduledata.AddUint(ctxt.Arch, 0)
   741  	}
   742  	if ctxt.BuildMode == BuildModePlugin {
   743  		addgostring(ctxt, ldr, moduledata, "go:link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   744  
   745  		pkghashes := ldr.CreateSymForUpdate("go:link.pkghashes", 0)
   746  		pkghashes.SetLocal(true)
   747  		pkghashes.SetType(sym.SRODATA)
   748  
   749  		for i, l := range ctxt.Library {
   750  			// pkghashes[i].name
   751  			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkgname.%d", i), l.Pkg)
   752  			// pkghashes[i].linktimehash
   753  			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkglinkhash.%d", i), string(l.Fingerprint[:]))
   754  			// pkghashes[i].runtimehash
   755  			hash := ldr.Lookup("go:link.pkghash."+l.Pkg, 0)
   756  			pkghashes.AddAddr(ctxt.Arch, hash)
   757  		}
   758  		moduledata.AddAddr(ctxt.Arch, pkghashes.Sym())
   759  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   760  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   761  	} else {
   762  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   763  		moduledata.AddUint(ctxt.Arch, 0)
   764  		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   765  		moduledata.AddUint(ctxt.Arch, 0)
   766  		moduledata.AddUint(ctxt.Arch, 0)
   767  	}
   768  	if len(ctxt.Shlibs) > 0 {
   769  		thismodulename := filepath.Base(*flagOutfile)
   770  		switch ctxt.BuildMode {
   771  		case BuildModeExe, BuildModePIE:
   772  			// When linking an executable, outfile is just "a.out". Make
   773  			// it something slightly more comprehensible.
   774  			thismodulename = "the executable"
   775  		}
   776  		addgostring(ctxt, ldr, moduledata, "go:link.thismodulename", thismodulename)
   777  
   778  		modulehashes := ldr.CreateSymForUpdate("go:link.abihashes", 0)
   779  		modulehashes.SetLocal(true)
   780  		modulehashes.SetType(sym.SRODATA)
   781  
   782  		for i, shlib := range ctxt.Shlibs {
   783  			// modulehashes[i].modulename
   784  			modulename := filepath.Base(shlib.Path)
   785  			addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.libname.%d", i), modulename)
   786  
   787  			// modulehashes[i].linktimehash
   788  			addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.linkhash.%d", i), string(shlib.Hash))
   789  
   790  			// modulehashes[i].runtimehash
   791  			abihash := ldr.LookupOrCreateSym("go:link.abihash."+modulename, 0)
   792  			ldr.SetAttrReachable(abihash, true)
   793  			modulehashes.AddAddr(ctxt.Arch, abihash)
   794  		}
   795  
   796  		moduledata.AddAddr(ctxt.Arch, modulehashes.Sym())
   797  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   798  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   799  	} else {
   800  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   801  		moduledata.AddUint(ctxt.Arch, 0)
   802  		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   803  		moduledata.AddUint(ctxt.Arch, 0)
   804  		moduledata.AddUint(ctxt.Arch, 0)
   805  	}
   806  
   807  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   808  	if hasmain {
   809  		moduledata.AddUint8(1)
   810  	} else {
   811  		moduledata.AddUint8(0)
   812  	}
   813  
   814  	// The rest of moduledata is zero initialized.
   815  	// When linking an object that does not contain the runtime we are
   816  	// creating the moduledata from scratch and it does not have a
   817  	// compiler-provided size, so read it from the type data.
   818  	moduledatatype := ldr.Lookup("type:runtime.moduledata", 0)
   819  	moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
   820  	moduledata.Grow(moduledata.Size())
   821  
   822  	lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0)
   823  	if lastmoduledatap.Type() != sym.SDYNIMPORT {
   824  		lastmoduledatap.SetType(sym.SNOPTRDATA)
   825  		lastmoduledatap.SetSize(0) // overwrite existing value
   826  		lastmoduledatap.SetData(nil)
   827  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata.Sym())
   828  	}
   829  	return symGroupType
   830  }
   831  
   832  // CarrierSymByType tracks carrier symbols and their sizes.
   833  var CarrierSymByType [sym.SXREF]struct {
   834  	Sym  loader.Sym
   835  	Size int64
   836  }
   837  
   838  func setCarrierSym(typ sym.SymKind, s loader.Sym) {
   839  	if CarrierSymByType[typ].Sym != 0 {
   840  		panic(fmt.Sprintf("carrier symbol for type %v already set", typ))
   841  	}
   842  	CarrierSymByType[typ].Sym = s
   843  }
   844  
   845  func setCarrierSize(typ sym.SymKind, sz int64) {
   846  	if CarrierSymByType[typ].Size != 0 {
   847  		panic(fmt.Sprintf("carrier symbol size for type %v already set", typ))
   848  	}
   849  	CarrierSymByType[typ].Size = sz
   850  }
   851  
   852  func isStaticTmp(name string) bool {
   853  	return strings.Contains(name, "."+obj.StaticNamePref)
   854  }
   855  
   856  // Mangle function name with ABI information.
   857  func mangleABIName(ctxt *Link, ldr *loader.Loader, x loader.Sym, name string) string {
   858  	// For functions with ABI wrappers, we have to make sure that we
   859  	// don't wind up with two symbol table entries with the same
   860  	// name (since this will generated an error from the external
   861  	// linker). If we have wrappers, keep the ABIInternal name
   862  	// unmangled since we want cross-load-module calls to target
   863  	// ABIInternal, and rename other symbols.
   864  	//
   865  	// TODO: avoid the ldr.Lookup calls below by instead using an aux
   866  	// sym or marker relocation to associate the wrapper with the
   867  	// wrapped function.
   868  	if !buildcfg.Experiment.RegabiWrappers {
   869  		return name
   870  	}
   871  
   872  	if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) != sym.SymVerABIInternal && ldr.SymVersion(x) < sym.SymVerStatic {
   873  		if s2 := ldr.Lookup(name, sym.SymVerABIInternal); s2 != 0 && ldr.SymType(s2) == sym.STEXT {
   874  			name = fmt.Sprintf("%s.abi%d", name, ldr.SymVersion(x))
   875  		}
   876  	}
   877  
   878  	// When loading a shared library, if a symbol has only one ABI,
   879  	// and the name is not mangled, we don't know what ABI it is.
   880  	// So we always mangle ABIInternal function name in shared linkage,
   881  	// except symbols that are exported to C. Type symbols are always
   882  	// ABIInternal so they are not mangled.
   883  	if ctxt.IsShared() {
   884  		if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type:") {
   885  			name = fmt.Sprintf("%s.abiinternal", name)
   886  		}
   887  	}
   888  
   889  	return name
   890  }