Source file src/cmd/link/internal/ld/symtab.go

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

View as plain text