Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/link/internal/ld

     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 = 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  	ctxt.Out.WriteString(name)
   304  	ctxt.Out.Write8(0)
   305  
   306  	symSize += int32(l) + 1 + int32(len(name)) + 1
   307  }
   308  
   309  func asmbPlan9Sym(ctxt *Link) {
   310  	ldr := ctxt.loader
   311  
   312  	// Add special runtime.text and runtime.etext symbols.
   313  	s := ldr.Lookup("runtime.text", 0)
   314  	if ldr.SymType(s) == sym.STEXT {
   315  		putplan9sym(ctxt, ldr, s, TextSym)
   316  	}
   317  	s = ldr.Lookup("runtime.etext", 0)
   318  	if ldr.SymType(s) == sym.STEXT {
   319  		putplan9sym(ctxt, ldr, s, TextSym)
   320  	}
   321  
   322  	// Add text symbols.
   323  	for _, s := range ctxt.Textp {
   324  		putplan9sym(ctxt, ldr, s, TextSym)
   325  	}
   326  
   327  	shouldBeInSymbolTable := func(s loader.Sym) bool {
   328  		if ldr.AttrNotInSymbolTable(s) {
   329  			return false
   330  		}
   331  		name := ldr.RawSymName(s) // TODO: try not to read the name
   332  		if name == "" || name[0] == '.' {
   333  			return false
   334  		}
   335  		return true
   336  	}
   337  
   338  	// Add data symbols and external references.
   339  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   340  		if !ldr.AttrReachable(s) {
   341  			continue
   342  		}
   343  		t := ldr.SymType(s)
   344  		if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
   345  			if t == sym.STLSBSS {
   346  				continue
   347  			}
   348  			if !shouldBeInSymbolTable(s) {
   349  				continue
   350  			}
   351  			char := DataSym
   352  			if t == sym.SBSS || t == sym.SNOPTRBSS {
   353  				char = BSSSym
   354  			}
   355  			putplan9sym(ctxt, ldr, s, char)
   356  		}
   357  	}
   358  }
   359  
   360  type byPkg []*sym.Library
   361  
   362  func (libs byPkg) Len() int {
   363  	return len(libs)
   364  }
   365  
   366  func (libs byPkg) Less(a, b int) bool {
   367  	return libs[a].Pkg < libs[b].Pkg
   368  }
   369  
   370  func (libs byPkg) Swap(a, b int) {
   371  	libs[a], libs[b] = libs[b], libs[a]
   372  }
   373  
   374  // Create a table with information on the text sections.
   375  // Return the symbol of the table, and number of sections.
   376  func textsectionmap(ctxt *Link) (loader.Sym, uint32) {
   377  	ldr := ctxt.loader
   378  	t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0)
   379  	t.SetType(sym.SRODATA)
   380  	nsections := int64(0)
   381  
   382  	for _, sect := range Segtext.Sections {
   383  		if sect.Name == ".text" {
   384  			nsections++
   385  		} else {
   386  			break
   387  		}
   388  	}
   389  	t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize))
   390  
   391  	off := int64(0)
   392  	n := 0
   393  
   394  	// The vaddr for each text section is the difference between the section's
   395  	// Vaddr and the Vaddr for the first text section as determined at compile
   396  	// time.
   397  
   398  	// The symbol for the first text section is named runtime.text as before.
   399  	// Additional text sections are named runtime.text.n where n is the
   400  	// order of creation starting with 1. These symbols provide the section's
   401  	// address after relocation by the linker.
   402  
   403  	textbase := Segtext.Sections[0].Vaddr
   404  	for _, sect := range Segtext.Sections {
   405  		if sect.Name != ".text" {
   406  			break
   407  		}
   408  		off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase)
   409  		off = t.SetUint(ctxt.Arch, off, sect.Length)
   410  		if n == 0 {
   411  			s := ldr.Lookup("runtime.text", 0)
   412  			if s == 0 {
   413  				ctxt.Errorf(s, "Unable to find symbol runtime.text\n")
   414  			}
   415  			off = t.SetAddr(ctxt.Arch, off, s)
   416  
   417  		} else {
   418  			s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
   419  			if s == 0 {
   420  				ctxt.Errorf(s, "Unable to find symbol runtime.text.%d\n", n)
   421  			}
   422  			off = t.SetAddr(ctxt.Arch, off, s)
   423  		}
   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.end", sym.SBSS, 0)
   457  	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   458  	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
   459  
   460  	// garbage collection symbols
   461  	s := ldr.CreateSymForUpdate("runtime.gcdata", 0)
   462  	s.SetType(sym.SRODATA)
   463  	s.SetSize(0)
   464  	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   465  
   466  	s = ldr.CreateSymForUpdate("runtime.gcbss", 0)
   467  	s.SetType(sym.SRODATA)
   468  	s.SetSize(0)
   469  	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   470  
   471  	// pseudo-symbols to mark locations of type, string, and go string data.
   472  	var symtype, symtyperel loader.Sym
   473  	if !ctxt.DynlinkingGo() {
   474  		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   475  			s = ldr.CreateSymForUpdate("type.*", 0)
   476  			s.SetType(sym.STYPE)
   477  			s.SetSize(0)
   478  			symtype = s.Sym()
   479  
   480  			s = ldr.CreateSymForUpdate("typerel.*", 0)
   481  			s.SetType(sym.STYPERELRO)
   482  			s.SetSize(0)
   483  			symtyperel = s.Sym()
   484  		} else {
   485  			s = ldr.CreateSymForUpdate("type.*", 0)
   486  			s.SetType(sym.STYPE)
   487  			s.SetSize(0)
   488  			symtype = s.Sym()
   489  			symtyperel = s.Sym()
   490  		}
   491  		setCarrierSym(sym.STYPE, symtype)
   492  		setCarrierSym(sym.STYPERELRO, symtyperel)
   493  	}
   494  
   495  	groupSym := func(name string, t sym.SymKind) loader.Sym {
   496  		s := ldr.CreateSymForUpdate(name, 0)
   497  		s.SetType(t)
   498  		s.SetSize(0)
   499  		s.SetLocal(true)
   500  		setCarrierSym(t, s.Sym())
   501  		return s.Sym()
   502  	}
   503  	var (
   504  		symgostring = groupSym("go.string.*", sym.SGOSTRING)
   505  		symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
   506  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   507  	)
   508  
   509  	var symgofuncrel loader.Sym
   510  	if !ctxt.DynlinkingGo() {
   511  		if ctxt.UseRelro() {
   512  			symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
   513  		} else {
   514  			symgofuncrel = symgofunc
   515  		}
   516  	}
   517  
   518  	symt := ldr.CreateSymForUpdate("runtime.symtab", 0)
   519  	symt.SetType(sym.SSYMTAB)
   520  	symt.SetSize(0)
   521  	symt.SetLocal(true)
   522  
   523  	// assign specific types so that they sort together.
   524  	// within a type they sort by size, so the .* symbols
   525  	// just defined above will be first.
   526  	// hide the specific symbols.
   527  	nsym := loader.Sym(ldr.NSym())
   528  	symGroupType := make([]sym.SymKind, nsym)
   529  	for s := loader.Sym(1); s < nsym; s++ {
   530  		if !ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && ldr.SymPkg(s) != "" {
   531  			ldr.SetAttrNotInSymbolTable(s, true)
   532  		}
   533  		if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) {
   534  			continue
   535  		}
   536  
   537  		name := ldr.SymName(s)
   538  		switch {
   539  		case strings.HasPrefix(name, "type."):
   540  			if !ctxt.DynlinkingGo() {
   541  				ldr.SetAttrNotInSymbolTable(s, true)
   542  			}
   543  			if ctxt.UseRelro() {
   544  				symGroupType[s] = sym.STYPERELRO
   545  				if symtyperel != 0 {
   546  					ldr.SetCarrierSym(s, symtyperel)
   547  				}
   548  			} else {
   549  				symGroupType[s] = sym.STYPE
   550  				if symtyperel != 0 {
   551  					ldr.SetCarrierSym(s, symtype)
   552  				}
   553  			}
   554  
   555  		case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro():
   556  			// Keep go.importpath symbols in the same section as types and
   557  			// names, as they can be referred to by a section offset.
   558  			symGroupType[s] = sym.STYPERELRO
   559  
   560  		case strings.HasPrefix(name, "go.string."):
   561  			symGroupType[s] = sym.SGOSTRING
   562  			ldr.SetAttrNotInSymbolTable(s, true)
   563  			ldr.SetCarrierSym(s, symgostring)
   564  
   565  		case strings.HasPrefix(name, "runtime.gcbits."):
   566  			symGroupType[s] = sym.SGCBITS
   567  			ldr.SetAttrNotInSymbolTable(s, true)
   568  			ldr.SetCarrierSym(s, symgcbits)
   569  
   570  		case strings.HasSuffix(name, "·f"):
   571  			if !ctxt.DynlinkingGo() {
   572  				ldr.SetAttrNotInSymbolTable(s, true)
   573  			}
   574  			if ctxt.UseRelro() {
   575  				symGroupType[s] = sym.SGOFUNCRELRO
   576  				if symgofuncrel != 0 {
   577  					ldr.SetCarrierSym(s, symgofuncrel)
   578  				}
   579  			} else {
   580  				symGroupType[s] = sym.SGOFUNC
   581  				ldr.SetCarrierSym(s, symgofunc)
   582  			}
   583  
   584  		case strings.HasPrefix(name, "gcargs."),
   585  			strings.HasPrefix(name, "gclocals."),
   586  			strings.HasPrefix(name, "gclocals·"),
   587  			ldr.SymType(s) == sym.SGOFUNC && s != symgofunc,
   588  			strings.HasSuffix(name, ".opendefer"),
   589  			strings.HasSuffix(name, ".arginfo0"),
   590  			strings.HasSuffix(name, ".arginfo1"):
   591  			symGroupType[s] = sym.SGOFUNC
   592  			ldr.SetAttrNotInSymbolTable(s, true)
   593  			ldr.SetCarrierSym(s, symgofunc)
   594  			align := int32(4)
   595  			if a := ldr.SymAlign(s); a < align {
   596  				ldr.SetSymAlign(s, align)
   597  			} else {
   598  				align = a
   599  			}
   600  			liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
   601  		}
   602  	}
   603  
   604  	if ctxt.BuildMode == BuildModeShared {
   605  		abihashgostr := ldr.CreateSymForUpdate("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   606  		abihashgostr.SetType(sym.SRODATA)
   607  		hashsym := ldr.LookupOrCreateSym("go.link.abihashbytes", 0)
   608  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   609  		abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym)))
   610  	}
   611  	if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   612  		for _, l := range ctxt.Library {
   613  			s := ldr.CreateSymForUpdate("go.link.pkghashbytes."+l.Pkg, 0)
   614  			s.SetType(sym.SRODATA)
   615  			s.SetSize(int64(len(l.Fingerprint)))
   616  			s.SetData(l.Fingerprint[:])
   617  			str := ldr.CreateSymForUpdate("go.link.pkghash."+l.Pkg, 0)
   618  			str.SetType(sym.SRODATA)
   619  			str.AddAddr(ctxt.Arch, s.Sym())
   620  			str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint)))
   621  		}
   622  	}
   623  
   624  	textsectionmapSym, nsections := textsectionmap(ctxt)
   625  
   626  	// Information about the layout of the executable image for the
   627  	// runtime to use. Any changes here must be matched by changes to
   628  	// the definition of moduledata in runtime/symtab.go.
   629  	// This code uses several global variables that are set by pcln.go:pclntab.
   630  	moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata)
   631  	// The pcHeader
   632  	moduledata.AddAddr(ctxt.Arch, pcln.pcheader)
   633  	// The function name slice
   634  	moduledata.AddAddr(ctxt.Arch, pcln.funcnametab)
   635  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.funcnametab)))
   636  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.funcnametab)))
   637  	// The cutab slice
   638  	moduledata.AddAddr(ctxt.Arch, pcln.cutab)
   639  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.cutab)))
   640  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.cutab)))
   641  	// The filetab slice
   642  	moduledata.AddAddr(ctxt.Arch, pcln.filetab)
   643  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab)))
   644  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.filetab)))
   645  	// The pctab slice
   646  	moduledata.AddAddr(ctxt.Arch, pcln.pctab)
   647  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab)))
   648  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pctab)))
   649  	// The pclntab slice
   650  	moduledata.AddAddr(ctxt.Arch, pcln.pclntab)
   651  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab)))
   652  	moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pcln.pclntab)))
   653  	// The ftab slice
   654  	moduledata.AddAddr(ctxt.Arch, pcln.pclntab)
   655  	moduledata.AddUint(ctxt.Arch, uint64(pcln.nfunc+1))
   656  	moduledata.AddUint(ctxt.Arch, uint64(pcln.nfunc+1))
   657  	// findfunctab
   658  	moduledata.AddAddr(ctxt.Arch, pcln.findfunctab)
   659  	// minpc, maxpc
   660  	moduledata.AddAddr(ctxt.Arch, pcln.firstFunc)
   661  	moduledata.AddAddrPlus(ctxt.Arch, pcln.lastFunc, ldr.SymSize(pcln.lastFunc))
   662  	// pointers to specific parts of the module
   663  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0))
   664  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0))
   665  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0))
   666  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0))
   667  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
   668  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0))
   669  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0))
   670  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0))
   671  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0))
   672  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0))
   673  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0))
   674  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0))
   675  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
   676  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
   677  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
   678  
   679  	if ctxt.IsAIX() && ctxt.IsExternal() {
   680  		// Add R_XCOFFREF relocation to prevent ld's garbage collection of
   681  		// runtime.rodata, runtime.erodata and runtime.epclntab.
   682  		addRef := func(name string) {
   683  			r, _ := moduledata.AddRel(objabi.R_XCOFFREF)
   684  			r.SetSym(ldr.Lookup(name, 0))
   685  			r.SetSiz(uint8(ctxt.Arch.PtrSize))
   686  		}
   687  		addRef("runtime.rodata")
   688  		addRef("runtime.erodata")
   689  		addRef("runtime.epclntab")
   690  	}
   691  
   692  	// text section information
   693  	moduledata.AddAddr(ctxt.Arch, textsectionmapSym)
   694  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   695  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   696  
   697  	// The typelinks slice
   698  	typelinkSym := ldr.Lookup("runtime.typelink", 0)
   699  	ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4
   700  	moduledata.AddAddr(ctxt.Arch, typelinkSym)
   701  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   702  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   703  	// The itablinks slice
   704  	itablinkSym := ldr.Lookup("runtime.itablink", 0)
   705  	nitablinks := uint64(ldr.SymSize(itablinkSym)) / uint64(ctxt.Arch.PtrSize)
   706  	moduledata.AddAddr(ctxt.Arch, itablinkSym)
   707  	moduledata.AddUint(ctxt.Arch, nitablinks)
   708  	moduledata.AddUint(ctxt.Arch, nitablinks)
   709  	// The ptab slice
   710  	if ptab := ldr.Lookup("go.plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) {
   711  		ldr.SetAttrLocal(ptab, true)
   712  		if ldr.SymType(ptab) != sym.SRODATA {
   713  			panic(fmt.Sprintf("go.plugin.tabs is %v, not SRODATA", ldr.SymType(ptab)))
   714  		}
   715  		nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff)
   716  		moduledata.AddAddr(ctxt.Arch, ptab)
   717  		moduledata.AddUint(ctxt.Arch, nentries)
   718  		moduledata.AddUint(ctxt.Arch, nentries)
   719  	} else {
   720  		moduledata.AddUint(ctxt.Arch, 0)
   721  		moduledata.AddUint(ctxt.Arch, 0)
   722  		moduledata.AddUint(ctxt.Arch, 0)
   723  	}
   724  	if ctxt.BuildMode == BuildModePlugin {
   725  		addgostring(ctxt, ldr, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   726  
   727  		pkghashes := ldr.CreateSymForUpdate("go.link.pkghashes", 0)
   728  		pkghashes.SetLocal(true)
   729  		pkghashes.SetType(sym.SRODATA)
   730  
   731  		for i, l := range ctxt.Library {
   732  			// pkghashes[i].name
   733  			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   734  			// pkghashes[i].linktimehash
   735  			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), string(l.Fingerprint[:]))
   736  			// pkghashes[i].runtimehash
   737  			hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0)
   738  			pkghashes.AddAddr(ctxt.Arch, hash)
   739  		}
   740  		moduledata.AddAddr(ctxt.Arch, pkghashes.Sym())
   741  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   742  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   743  	} else {
   744  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   745  		moduledata.AddUint(ctxt.Arch, 0)
   746  		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   747  		moduledata.AddUint(ctxt.Arch, 0)
   748  		moduledata.AddUint(ctxt.Arch, 0)
   749  	}
   750  	if len(ctxt.Shlibs) > 0 {
   751  		thismodulename := filepath.Base(*flagOutfile)
   752  		switch ctxt.BuildMode {
   753  		case BuildModeExe, BuildModePIE:
   754  			// When linking an executable, outfile is just "a.out". Make
   755  			// it something slightly more comprehensible.
   756  			thismodulename = "the executable"
   757  		}
   758  		addgostring(ctxt, ldr, moduledata, "go.link.thismodulename", thismodulename)
   759  
   760  		modulehashes := ldr.CreateSymForUpdate("go.link.abihashes", 0)
   761  		modulehashes.SetLocal(true)
   762  		modulehashes.SetType(sym.SRODATA)
   763  
   764  		for i, shlib := range ctxt.Shlibs {
   765  			// modulehashes[i].modulename
   766  			modulename := filepath.Base(shlib.Path)
   767  			addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   768  
   769  			// modulehashes[i].linktimehash
   770  			addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   771  
   772  			// modulehashes[i].runtimehash
   773  			abihash := ldr.LookupOrCreateSym("go.link.abihash."+modulename, 0)
   774  			ldr.SetAttrReachable(abihash, true)
   775  			modulehashes.AddAddr(ctxt.Arch, abihash)
   776  		}
   777  
   778  		moduledata.AddAddr(ctxt.Arch, modulehashes.Sym())
   779  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   780  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   781  	} else {
   782  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   783  		moduledata.AddUint(ctxt.Arch, 0)
   784  		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   785  		moduledata.AddUint(ctxt.Arch, 0)
   786  		moduledata.AddUint(ctxt.Arch, 0)
   787  	}
   788  
   789  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   790  	if hasmain {
   791  		moduledata.AddUint8(1)
   792  	} else {
   793  		moduledata.AddUint8(0)
   794  	}
   795  
   796  	// The rest of moduledata is zero initialized.
   797  	// When linking an object that does not contain the runtime we are
   798  	// creating the moduledata from scratch and it does not have a
   799  	// compiler-provided size, so read it from the type data.
   800  	moduledatatype := ldr.Lookup("type.runtime.moduledata", 0)
   801  	moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
   802  	moduledata.Grow(moduledata.Size())
   803  
   804  	lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0)
   805  	if lastmoduledatap.Type() != sym.SDYNIMPORT {
   806  		lastmoduledatap.SetType(sym.SNOPTRDATA)
   807  		lastmoduledatap.SetSize(0) // overwrite existing value
   808  		lastmoduledatap.SetData(nil)
   809  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata.Sym())
   810  	}
   811  	return symGroupType
   812  }
   813  
   814  // CarrierSymByType tracks carrier symbols and their sizes.
   815  var CarrierSymByType [sym.SXREF]struct {
   816  	Sym  loader.Sym
   817  	Size int64
   818  }
   819  
   820  func setCarrierSym(typ sym.SymKind, s loader.Sym) {
   821  	if CarrierSymByType[typ].Sym != 0 {
   822  		panic(fmt.Sprintf("carrier symbol for type %v already set", typ))
   823  	}
   824  	CarrierSymByType[typ].Sym = s
   825  }
   826  
   827  func setCarrierSize(typ sym.SymKind, sz int64) {
   828  	if CarrierSymByType[typ].Size != 0 {
   829  		panic(fmt.Sprintf("carrier symbol size for type %v already set", typ))
   830  	}
   831  	CarrierSymByType[typ].Size = sz
   832  }
   833  
   834  func isStaticTmp(name string) bool {
   835  	return strings.Contains(name, "."+obj.StaticNamePref)
   836  }
   837  
   838  // Mangle function name with ABI information.
   839  func mangleABIName(ctxt *Link, ldr *loader.Loader, x loader.Sym, name string) string {
   840  	// For functions with ABI wrappers, we have to make sure that we
   841  	// don't wind up with two symbol table entries with the same
   842  	// name (since this will generated an error from the external
   843  	// linker). If we have wrappers, keep the ABIInternal name
   844  	// unmangled since we want cross-load-module calls to target
   845  	// ABIInternal, and rename other symbols.
   846  	//
   847  	// TODO: avoid the ldr.Lookup calls below by instead using an aux
   848  	// sym or marker relocation to associate the wrapper with the
   849  	// wrapped function.
   850  	if !buildcfg.Experiment.RegabiWrappers {
   851  		return name
   852  	}
   853  
   854  	if !ldr.IsExternal(x) && ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) != sym.SymVerABIInternal {
   855  		if s2 := ldr.Lookup(name, sym.SymVerABIInternal); s2 != 0 && ldr.SymType(s2) == sym.STEXT {
   856  			name = fmt.Sprintf("%s.abi%d", name, ldr.SymVersion(x))
   857  		}
   858  	}
   859  
   860  	// When loading a shared library, if a symbol has only one ABI,
   861  	// and the name is not mangled, we don't know what ABI it is.
   862  	// So we always mangle ABIInternal function name in shared linkage,
   863  	// except symbols that are exported to C. Type symbols are always
   864  	// ABIInternal so they are not mangled.
   865  	if ctxt.IsShared() {
   866  		if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type.") {
   867  			name = fmt.Sprintf("%s.abiinternal", name)
   868  		}
   869  	}
   870  
   871  	return name
   872  }
   873  

View as plain text