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