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

View as plain text