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.ReplaceAll(sname, "·", ".")
   159  	}
   160  
   161  	if ctxt.DynlinkingGo() && bind == elf.STB_GLOBAL && curbind == elf.STB_LOCAL && ldr.SymType(x).IsText() {
   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).IsText() {
   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).IsText() {
   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.SFirstUnallocated {
   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).IsText() {
   319  		putplan9sym(ctxt, ldr, s, TextSym)
   320  	}
   321  	s = ldr.Lookup("runtime.etext", 0)
   322  	if ldr.SymType(s).IsText() {
   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.SFirstUnallocated { // 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  // Create a table with information on the text sections.
   365  // Return the symbol of the table, and number of sections.
   366  func textsectionmap(ctxt *Link) (loader.Sym, uint32) {
   367  	ldr := ctxt.loader
   368  	t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0)
   369  	t.SetType(sym.SRODATA)
   370  	nsections := int64(0)
   371  
   372  	for _, sect := range Segtext.Sections {
   373  		if sect.Name == ".text" {
   374  			nsections++
   375  		} else {
   376  			break
   377  		}
   378  	}
   379  	t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize))
   380  
   381  	off := int64(0)
   382  	n := 0
   383  
   384  	// The vaddr for each text section is the difference between the section's
   385  	// Vaddr and the Vaddr for the first text section as determined at compile
   386  	// time.
   387  
   388  	// The symbol for the first text section is named runtime.text as before.
   389  	// Additional text sections are named runtime.text.n where n is the
   390  	// order of creation starting with 1. These symbols provide the section's
   391  	// address after relocation by the linker.
   392  
   393  	textbase := Segtext.Sections[0].Vaddr
   394  	for _, sect := range Segtext.Sections {
   395  		if sect.Name != ".text" {
   396  			break
   397  		}
   398  		// The fields written should match runtime/symtab.go:textsect.
   399  		// They are designed to minimize runtime calculations.
   400  		vaddr := sect.Vaddr - textbase
   401  		off = t.SetUint(ctxt.Arch, off, vaddr) // field vaddr
   402  		end := vaddr + sect.Length
   403  		off = t.SetUint(ctxt.Arch, off, end) // field end
   404  		name := "runtime.text"
   405  		if n != 0 {
   406  			name = fmt.Sprintf("runtime.text.%d", n)
   407  		}
   408  		s := ldr.Lookup(name, 0)
   409  		if s == 0 {
   410  			ctxt.Errorf(s, "Unable to find symbol %s\n", name)
   411  		}
   412  		off = t.SetAddr(ctxt.Arch, off, s) // field baseaddr
   413  		n++
   414  	}
   415  	return t.Sym(), uint32(n)
   416  }
   417  
   418  func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
   419  	ldr := ctxt.loader
   420  
   421  	if !ctxt.IsAIX() && !ctxt.IsWasm() {
   422  		switch ctxt.BuildMode {
   423  		case BuildModeCArchive, BuildModeCShared:
   424  			s := ldr.Lookup(*flagEntrySymbol, sym.SymVerABI0)
   425  			if s != 0 {
   426  				addinitarrdata(ctxt, ldr, s)
   427  			}
   428  		}
   429  	}
   430  
   431  	// Define these so that they'll get put into the symbol table.
   432  	// data.c:/^address will provide the actual values.
   433  	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
   434  	ctxt.xdefine("runtime.erodata", sym.SRODATAEND, 0)
   435  	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
   436  	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
   437  	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
   438  	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATAEND, 0)
   439  	ctxt.xdefine("runtime.data", sym.SDATA, 0)
   440  	ctxt.xdefine("runtime.edata", sym.SDATAEND, 0)
   441  	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
   442  	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
   443  	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
   444  	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
   445  	ctxt.xdefine("runtime.covctrs", sym.SNOPTRBSS, 0)
   446  	ctxt.xdefine("runtime.ecovctrs", sym.SNOPTRBSS, 0)
   447  	ctxt.xdefine("runtime.end", sym.SBSS, 0)
   448  	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   449  
   450  	// garbage collection symbols
   451  	s := ldr.CreateSymForUpdate("runtime.gcdata", 0)
   452  	s.SetType(sym.SRODATA)
   453  	s.SetSize(0)
   454  	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   455  
   456  	s = ldr.CreateSymForUpdate("runtime.gcbss", 0)
   457  	s.SetType(sym.SRODATA)
   458  	s.SetSize(0)
   459  	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   460  
   461  	// pseudo-symbols to mark locations of type, string, and go string data.
   462  	var symtype, symtyperel loader.Sym
   463  	if !ctxt.DynlinkingGo() {
   464  		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   465  			s = ldr.CreateSymForUpdate("type:*", 0)
   466  			s.SetType(sym.STYPE)
   467  			s.SetSize(0)
   468  			s.SetAlign(int32(ctxt.Arch.PtrSize))
   469  			symtype = s.Sym()
   470  
   471  			s = ldr.CreateSymForUpdate("typerel.*", 0)
   472  			s.SetType(sym.STYPERELRO)
   473  			s.SetSize(0)
   474  			s.SetAlign(int32(ctxt.Arch.PtrSize))
   475  			symtyperel = s.Sym()
   476  		} else {
   477  			s = ldr.CreateSymForUpdate("type:*", 0)
   478  			s.SetType(sym.STYPE)
   479  			s.SetSize(0)
   480  			s.SetAlign(int32(ctxt.Arch.PtrSize))
   481  			symtype = s.Sym()
   482  			symtyperel = s.Sym()
   483  		}
   484  		setCarrierSym(sym.STYPE, symtype)
   485  		setCarrierSym(sym.STYPERELRO, symtyperel)
   486  	}
   487  
   488  	groupSym := func(name string, t sym.SymKind) loader.Sym {
   489  		s := ldr.CreateSymForUpdate(name, 0)
   490  		s.SetType(t)
   491  		s.SetSize(0)
   492  		s.SetAlign(int32(ctxt.Arch.PtrSize))
   493  		s.SetLocal(true)
   494  		setCarrierSym(t, s.Sym())
   495  		return s.Sym()
   496  	}
   497  	var (
   498  		symgostring = groupSym("go:string.*", sym.SGOSTRING)
   499  		symgofunc   = groupSym("go:func.*", sym.SGOFUNC)
   500  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   501  	)
   502  
   503  	symgofuncrel := symgofunc
   504  	if ctxt.UseRelro() {
   505  		symgofuncrel = groupSym("go:funcrel.*", sym.SGOFUNCRELRO)
   506  	}
   507  
   508  	// assign specific types so that they sort together.
   509  	// within a type they sort by size, so the .* symbols
   510  	// just defined above will be first.
   511  	// hide the specific symbols.
   512  	// Some of these symbol section conditions are duplicated
   513  	// in cmd/internal/obj.contentHashSection.
   514  	nsym := loader.Sym(ldr.NSym())
   515  	symGroupType := make([]sym.SymKind, nsym)
   516  	for s := loader.Sym(1); s < nsym; s++ {
   517  		if (!ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && ldr.SymPkg(s) != "") || (ctxt.LinkMode == LinkInternal && ldr.SymType(s) == sym.SCOVERAGE_COUNTER) {
   518  			ldr.SetAttrNotInSymbolTable(s, true)
   519  		}
   520  		if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) {
   521  			continue
   522  		}
   523  
   524  		name := ldr.SymName(s)
   525  		switch {
   526  		case strings.HasPrefix(name, "go:string."):
   527  			symGroupType[s] = sym.SGOSTRING
   528  			ldr.SetAttrNotInSymbolTable(s, true)
   529  			ldr.SetCarrierSym(s, symgostring)
   530  
   531  		case strings.HasPrefix(name, "runtime.gcbits."),
   532  			strings.HasPrefix(name, "type:.gcprog."):
   533  			symGroupType[s] = sym.SGCBITS
   534  			ldr.SetAttrNotInSymbolTable(s, true)
   535  			ldr.SetCarrierSym(s, symgcbits)
   536  
   537  		case strings.HasSuffix(name, "·f"):
   538  			if !ctxt.DynlinkingGo() {
   539  				ldr.SetAttrNotInSymbolTable(s, true)
   540  			}
   541  			if ctxt.UseRelro() {
   542  				symGroupType[s] = sym.SGOFUNCRELRO
   543  				if !ctxt.DynlinkingGo() {
   544  					ldr.SetCarrierSym(s, symgofuncrel)
   545  				}
   546  			} else {
   547  				symGroupType[s] = sym.SGOFUNC
   548  				ldr.SetCarrierSym(s, symgofunc)
   549  			}
   550  
   551  		case strings.HasPrefix(name, "gcargs."),
   552  			strings.HasPrefix(name, "gclocals."),
   553  			strings.HasPrefix(name, "gclocals·"),
   554  			ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, // inltree, see pcln.go
   555  			strings.HasSuffix(name, ".opendefer"),
   556  			strings.HasSuffix(name, ".arginfo0"),
   557  			strings.HasSuffix(name, ".arginfo1"),
   558  			strings.HasSuffix(name, ".argliveinfo"),
   559  			strings.HasSuffix(name, ".wrapinfo"),
   560  			strings.HasSuffix(name, ".args_stackmap"),
   561  			strings.HasSuffix(name, ".stkobj"):
   562  			ldr.SetAttrNotInSymbolTable(s, true)
   563  			symGroupType[s] = sym.SGOFUNC
   564  			ldr.SetCarrierSym(s, symgofunc)
   565  			if ctxt.Debugvlog != 0 {
   566  				align := ldr.SymAlign(s)
   567  				liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
   568  			}
   569  
   570  		// Note: Check for "type:" prefix after checking for .arginfo1 suffix.
   571  		// That way symbols like "type:.eq.[2]interface {}.arginfo1" that belong
   572  		// in go:func.* end up there.
   573  		case strings.HasPrefix(name, "type:"):
   574  			if !ctxt.DynlinkingGo() {
   575  				ldr.SetAttrNotInSymbolTable(s, true)
   576  			}
   577  			if ctxt.UseRelro() {
   578  				symGroupType[s] = sym.STYPERELRO
   579  				if symtyperel != 0 {
   580  					ldr.SetCarrierSym(s, symtyperel)
   581  				}
   582  			} else {
   583  				symGroupType[s] = sym.STYPE
   584  				if symtyperel != 0 {
   585  					ldr.SetCarrierSym(s, symtype)
   586  				}
   587  			}
   588  		}
   589  	}
   590  
   591  	if ctxt.BuildMode == BuildModeShared {
   592  		abihashgostr := ldr.CreateSymForUpdate("go:link.abihash."+filepath.Base(*flagOutfile), 0)
   593  		abihashgostr.SetType(sym.SRODATA)
   594  		hashsym := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
   595  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   596  		abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym)))
   597  	}
   598  	if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   599  		for _, l := range ctxt.Library {
   600  			s := ldr.CreateSymForUpdate("go:link.pkghashbytes."+l.Pkg, 0)
   601  			s.SetType(sym.SRODATA)
   602  			s.SetSize(int64(len(l.Fingerprint)))
   603  			s.SetData(l.Fingerprint[:])
   604  			str := ldr.CreateSymForUpdate("go:link.pkghash."+l.Pkg, 0)
   605  			str.SetType(sym.SRODATA)
   606  			str.AddAddr(ctxt.Arch, s.Sym())
   607  			str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint)))
   608  		}
   609  	}
   610  
   611  	textsectionmapSym, nsections := textsectionmap(ctxt)
   612  
   613  	// Information about the layout of the executable image for the
   614  	// runtime to use. Any changes here must be matched by changes to
   615  	// the definition of moduledata in runtime/symtab.go.
   616  	// This code uses several global variables that are set by pcln.go:pclntab.
   617  	moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata)
   618  
   619  	slice := func(sym loader.Sym, len uint64) {
   620  		moduledata.AddAddr(ctxt.Arch, sym)
   621  		moduledata.AddUint(ctxt.Arch, len)
   622  		moduledata.AddUint(ctxt.Arch, len)
   623  	}
   624  
   625  	sliceSym := func(sym loader.Sym) {
   626  		slice(sym, uint64(ldr.SymSize(sym)))
   627  	}
   628  
   629  	nilSlice := func() {
   630  		moduledata.AddUint(ctxt.Arch, 0)
   631  		moduledata.AddUint(ctxt.Arch, 0)
   632  		moduledata.AddUint(ctxt.Arch, 0)
   633  	}
   634  
   635  	// The pcHeader
   636  	moduledata.AddAddr(ctxt.Arch, pcln.pcheader)
   637  
   638  	// The function name slice
   639  	sliceSym(pcln.funcnametab)
   640  
   641  	// The cutab slice
   642  	slice(pcln.cutab, uint64(ldr.SymSize(pcln.cutab))/4)
   643  
   644  	// The filetab slice
   645  	sliceSym(pcln.filetab)
   646  
   647  	// The pctab slice
   648  	sliceSym(pcln.pctab)
   649  
   650  	// The pclntab slice
   651  	sliceSym(pcln.pclntab)
   652  
   653  	// The ftab slice
   654  	slice(pcln.pclntab, uint64(pcln.nfunc+1))
   655  
   656  	// findfunctab
   657  	moduledata.AddAddr(ctxt.Arch, pcln.findfunctab)
   658  	// minpc, maxpc
   659  	moduledata.AddAddr(ctxt.Arch, pcln.firstFunc)
   660  	moduledata.AddAddrPlus(ctxt.Arch, pcln.lastFunc, ldr.SymSize(pcln.lastFunc))
   661  	// pointers to specific parts of the module
   662  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0))
   663  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0))
   664  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0))
   665  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0))
   666  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
   667  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0))
   668  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0))
   669  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0))
   670  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0))
   671  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0))
   672  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.covctrs", 0))
   673  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ecovctrs", 0))
   674  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0))
   675  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0))
   676  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
   677  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
   678  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
   679  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0))
   680  	moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go:func.*", 0))
   681  
   682  	if ctxt.IsAIX() && ctxt.IsExternal() {
   683  		// Add R_XCOFFREF relocation to prevent ld's garbage collection of
   684  		// the following symbols. They might not be referenced in the program.
   685  		addRef := func(name string) {
   686  			s := ldr.Lookup(name, 0)
   687  			if s == 0 {
   688  				return
   689  			}
   690  			r, _ := moduledata.AddRel(objabi.R_XCOFFREF)
   691  			r.SetSym(s)
   692  			r.SetSiz(uint8(ctxt.Arch.PtrSize))
   693  		}
   694  		addRef("runtime.rodata")
   695  		addRef("runtime.erodata")
   696  		addRef("runtime.epclntab")
   697  		// As we use relative addressing for text symbols in functab, it is
   698  		// important that the offsets we computed stay unchanged by the external
   699  		// linker, i.e. all symbols in Textp should not be removed.
   700  		// Most of them are actually referenced (our deadcode pass ensures that),
   701  		// except go:buildid which is generated late and not used by the program.
   702  		addRef("go:buildid")
   703  	}
   704  	if ctxt.IsAIX() {
   705  		// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol
   706  		// does not work. See data.go:relocsym, case R_ADDR.
   707  		// Here we record the unrelocated address in aixStaticDataBase (it is
   708  		// unrelocated as it is in RODATA) so we can compute the delta at
   709  		// run time.
   710  		sb := ldr.CreateSymForUpdate("runtime.aixStaticDataBase", 0)
   711  		sb.SetSize(0)
   712  		sb.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
   713  		sb.SetType(sym.SRODATA)
   714  	}
   715  
   716  	// text section information
   717  	slice(textsectionmapSym, uint64(nsections))
   718  
   719  	// The typelinks slice
   720  	typelinkSym := ldr.Lookup("runtime.typelink", 0)
   721  	ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4
   722  	slice(typelinkSym, ntypelinks)
   723  
   724  	// The itablinks slice
   725  	itablinkSym := ldr.Lookup("runtime.itablink", 0)
   726  	nitablinks := uint64(ldr.SymSize(itablinkSym)) / uint64(ctxt.Arch.PtrSize)
   727  	slice(itablinkSym, nitablinks)
   728  
   729  	// The ptab slice
   730  	if ptab := ldr.Lookup("go:plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) {
   731  		ldr.SetAttrLocal(ptab, true)
   732  		if ldr.SymType(ptab) != sym.SRODATA {
   733  			panic(fmt.Sprintf("go:plugin.tabs is %v, not SRODATA", ldr.SymType(ptab)))
   734  		}
   735  		nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff)
   736  		slice(ptab, nentries)
   737  	} else {
   738  		nilSlice()
   739  	}
   740  
   741  	if ctxt.BuildMode == BuildModePlugin {
   742  		addgostring(ctxt, ldr, moduledata, "go:link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   743  
   744  		pkghashes := ldr.CreateSymForUpdate("go:link.pkghashes", 0)
   745  		pkghashes.SetLocal(true)
   746  		pkghashes.SetType(sym.SRODATA)
   747  
   748  		for i, l := range ctxt.Library {
   749  			// pkghashes[i].name
   750  			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkgname.%d", i), l.Pkg)
   751  			// pkghashes[i].linktimehash
   752  			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkglinkhash.%d", i), string(l.Fingerprint[:]))
   753  			// pkghashes[i].runtimehash
   754  			hash := ldr.Lookup("go:link.pkghash."+l.Pkg, 0)
   755  			pkghashes.AddAddr(ctxt.Arch, hash)
   756  		}
   757  		slice(pkghashes.Sym(), uint64(len(ctxt.Library)))
   758  	} else {
   759  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   760  		moduledata.AddUint(ctxt.Arch, 0)
   761  		nilSlice() // pkghashes slice
   762  	}
   763  	// Add inittasks slice
   764  	t := ctxt.mainInittasks
   765  	if t != 0 {
   766  		moduledata.AddAddr(ctxt.Arch, t)
   767  		moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(t)/int64(ctxt.Arch.PtrSize)))
   768  		moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(t)/int64(ctxt.Arch.PtrSize)))
   769  	} else {
   770  		// Some build modes have no inittasks, like a shared library.
   771  		// Its inittask list will be constructed by a higher-level
   772  		// linking step.
   773  		// This branch can also happen if there are no init tasks at all.
   774  		moduledata.AddUint(ctxt.Arch, 0)
   775  		moduledata.AddUint(ctxt.Arch, 0)
   776  		moduledata.AddUint(ctxt.Arch, 0)
   777  	}
   778  
   779  	if len(ctxt.Shlibs) > 0 {
   780  		thismodulename := filepath.Base(*flagOutfile)
   781  		switch ctxt.BuildMode {
   782  		case BuildModeExe, BuildModePIE:
   783  			// When linking an executable, outfile is just "a.out". Make
   784  			// it something slightly more comprehensible.
   785  			thismodulename = "the executable"
   786  		}
   787  		addgostring(ctxt, ldr, moduledata, "go:link.thismodulename", thismodulename)
   788  
   789  		modulehashes := ldr.CreateSymForUpdate("go:link.abihashes", 0)
   790  		modulehashes.SetLocal(true)
   791  		modulehashes.SetType(sym.SRODATA)
   792  
   793  		for i, shlib := range ctxt.Shlibs {
   794  			// modulehashes[i].modulename
   795  			modulename := filepath.Base(shlib.Path)
   796  			addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.libname.%d", i), modulename)
   797  
   798  			// modulehashes[i].linktimehash
   799  			addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.linkhash.%d", i), string(shlib.Hash))
   800  
   801  			// modulehashes[i].runtimehash
   802  			abihash := ldr.LookupOrCreateSym("go:link.abihash."+modulename, 0)
   803  			ldr.SetAttrReachable(abihash, true)
   804  			modulehashes.AddAddr(ctxt.Arch, abihash)
   805  		}
   806  
   807  		slice(modulehashes.Sym(), uint64(len(ctxt.Shlibs)))
   808  	} else {
   809  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   810  		moduledata.AddUint(ctxt.Arch, 0)
   811  		nilSlice() // moduleshashes slice
   812  	}
   813  
   814  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   815  	if hasmain {
   816  		moduledata.AddUint8(1)
   817  	} else {
   818  		moduledata.AddUint8(0)
   819  	}
   820  
   821  	// The rest of moduledata is zero initialized.
   822  	// When linking an object that does not contain the runtime we are
   823  	// creating the moduledata from scratch and it does not have a
   824  	// compiler-provided size, so read it from the type data.
   825  	moduledatatype := ldr.Lookup("type:runtime.moduledata", 0)
   826  	moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
   827  	moduledata.Grow(moduledata.Size())
   828  
   829  	lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0)
   830  	if lastmoduledatap.Type() != sym.SDYNIMPORT {
   831  		lastmoduledatap.SetType(sym.SNOPTRDATA)
   832  		lastmoduledatap.SetSize(0) // overwrite existing value
   833  		lastmoduledatap.SetData(nil)
   834  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata.Sym())
   835  	}
   836  	return symGroupType
   837  }
   838  
   839  // CarrierSymByType tracks carrier symbols and their sizes.
   840  var CarrierSymByType [sym.SFirstUnallocated]struct {
   841  	Sym  loader.Sym
   842  	Size int64
   843  }
   844  
   845  func setCarrierSym(typ sym.SymKind, s loader.Sym) {
   846  	if CarrierSymByType[typ].Sym != 0 {
   847  		panic(fmt.Sprintf("carrier symbol for type %v already set", typ))
   848  	}
   849  	CarrierSymByType[typ].Sym = s
   850  }
   851  
   852  func setCarrierSize(typ sym.SymKind, sz int64) {
   853  	if typ == sym.Sxxx {
   854  		panic("setCarrierSize(Sxxx)")
   855  	}
   856  	if CarrierSymByType[typ].Size != 0 {
   857  		panic(fmt.Sprintf("carrier symbol size for type %v already set", typ))
   858  	}
   859  	CarrierSymByType[typ].Size = sz
   860  }
   861  
   862  func isStaticTmp(name string) bool {
   863  	return strings.Contains(name, "."+obj.StaticNamePrefix)
   864  }
   865  
   866  // Mangle function name with ABI information.
   867  func mangleABIName(ctxt *Link, ldr *loader.Loader, x loader.Sym, name string) string {
   868  	// For functions with ABI wrappers, we have to make sure that we
   869  	// don't wind up with two symbol table entries with the same
   870  	// name (since this will generated an error from the external
   871  	// linker). If we have wrappers, keep the ABIInternal name
   872  	// unmangled since we want cross-load-module calls to target
   873  	// ABIInternal, and rename other symbols.
   874  	//
   875  	// TODO: avoid the ldr.Lookup calls below by instead using an aux
   876  	// sym or marker relocation to associate the wrapper with the
   877  	// wrapped function.
   878  	if !buildcfg.Experiment.RegabiWrappers {
   879  		return name
   880  	}
   881  
   882  	if ldr.SymType(x).IsText() && ldr.SymVersion(x) != sym.SymVerABIInternal && ldr.SymVersion(x) < sym.SymVerStatic {
   883  		if s2 := ldr.Lookup(name, sym.SymVerABIInternal); s2 != 0 && ldr.SymType(s2).IsText() {
   884  			name = fmt.Sprintf("%s.abi%d", name, ldr.SymVersion(x))
   885  		}
   886  	}
   887  
   888  	// When loading a shared library, if a symbol has only one ABI,
   889  	// and the name is not mangled, we don't know what ABI it is.
   890  	// So we always mangle ABIInternal function name in shared linkage,
   891  	// except symbols that are exported to C. Type symbols are always
   892  	// ABIInternal so they are not mangled.
   893  	if ctxt.IsShared() {
   894  		if ldr.SymType(x).IsText() && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type:") {
   895  			name = fmt.Sprintf("%s.abiinternal", name)
   896  		}
   897  	}
   898  
   899  	return name
   900  }
   901  

View as plain text