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

View as plain text