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

View as plain text