...
Run Format

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

Documentation: cmd/link/internal/ld

     1  // Inferno utils/6l/span.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/span.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package ld
    32  
    33  import (
    34  	"cmd/internal/objabi"
    35  	"cmd/internal/sys"
    36  	"cmd/link/internal/sym"
    37  	"fmt"
    38  	"path/filepath"
    39  	"strings"
    40  )
    41  
    42  // Symbol table.
    43  
    44  func putelfstr(s string) int {
    45  	if len(Elfstrdat) == 0 && s != "" {
    46  		// first entry must be empty string
    47  		putelfstr("")
    48  	}
    49  
    50  	off := len(Elfstrdat)
    51  	Elfstrdat = append(Elfstrdat, s...)
    52  	Elfstrdat = append(Elfstrdat, 0)
    53  	return off
    54  }
    55  
    56  func putelfsyment(out *OutBuf, off int, addr int64, size int64, info int, shndx int, other int) {
    57  	if elf64 {
    58  		out.Write32(uint32(off))
    59  		out.Write8(uint8(info))
    60  		out.Write8(uint8(other))
    61  		out.Write16(uint16(shndx))
    62  		out.Write64(uint64(addr))
    63  		out.Write64(uint64(size))
    64  		Symsize += ELF64SYMSIZE
    65  	} else {
    66  		out.Write32(uint32(off))
    67  		out.Write32(uint32(addr))
    68  		out.Write32(uint32(size))
    69  		out.Write8(uint8(info))
    70  		out.Write8(uint8(other))
    71  		out.Write16(uint16(shndx))
    72  		Symsize += ELF32SYMSIZE
    73  	}
    74  }
    75  
    76  var numelfsym = 1 // 0 is reserved
    77  
    78  var elfbind int
    79  
    80  func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go_ *sym.Symbol) {
    81  	var typ int
    82  
    83  	switch t {
    84  	default:
    85  		return
    86  
    87  	case TextSym:
    88  		typ = STT_FUNC
    89  
    90  	case DataSym, BSSSym:
    91  		typ = STT_OBJECT
    92  
    93  	case UndefinedSym:
    94  		// ElfType is only set for symbols read from Go shared libraries, but
    95  		// for other symbols it is left as STT_NOTYPE which is fine.
    96  		typ = int(x.ElfType)
    97  
    98  	case TLSSym:
    99  		typ = STT_TLS
   100  	}
   101  
   102  	size := x.Size
   103  	if t == UndefinedSym {
   104  		size = 0
   105  	}
   106  
   107  	xo := x
   108  	for xo.Outer != nil {
   109  		xo = xo.Outer
   110  	}
   111  
   112  	var elfshnum int
   113  	if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ {
   114  		elfshnum = SHN_UNDEF
   115  	} else {
   116  		if xo.Sect == nil {
   117  			Errorf(x, "missing section in putelfsym")
   118  			return
   119  		}
   120  		if xo.Sect.Elfsect == nil {
   121  			Errorf(x, "missing ELF section in putelfsym")
   122  			return
   123  		}
   124  		elfshnum = xo.Sect.Elfsect.(*ElfShdr).shnum
   125  	}
   126  
   127  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   128  	// maybe one day STB_WEAK.
   129  	bind := STB_GLOBAL
   130  
   131  	if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
   132  		bind = STB_LOCAL
   133  	}
   134  
   135  	// In external linking mode, we have to invoke gcc with -rdynamic
   136  	// to get the exported symbols put into the dynamic symbol table.
   137  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   138  	// mark all Go symbols local (not global) in the final executable.
   139  	// But when we're dynamically linking, we need all those global symbols.
   140  	if !ctxt.DynlinkingGo() && ctxt.LinkMode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF {
   141  		bind = STB_LOCAL
   142  	}
   143  
   144  	if ctxt.LinkMode == LinkExternal && elfshnum != SHN_UNDEF {
   145  		addr -= int64(xo.Sect.Vaddr)
   146  	}
   147  	other := STV_DEFAULT
   148  	if x.Attr.VisibilityHidden() {
   149  		// TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when
   150  		// internally linking. But STV_HIDDEN visibility only matters in object
   151  		// files and shared libraries, and as we are a long way from implementing
   152  		// internal linking for shared libraries and only create object files when
   153  		// externally linking, I don't think this makes a lot of sense.
   154  		other = STV_HIDDEN
   155  	}
   156  	if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
   157  		// On ppc64 the top three bits of the st_other field indicate how
   158  		// many instructions separate the global and local entry points. In
   159  		// our case it is two instructions, indicated by the value 3.
   160  		// The conditions here match those in preprocess in
   161  		// cmd/internal/obj/ppc64/obj9.go, which is where the
   162  		// instructions are inserted.
   163  		other |= 3 << 5
   164  	}
   165  
   166  	// When dynamically linking, we create Symbols by reading the names from
   167  	// the symbol tables of the shared libraries and so the names need to
   168  	// match exactly. Tools like DTrace will have to wait for now.
   169  	if !ctxt.DynlinkingGo() {
   170  		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
   171  		s = strings.Replace(s, "·", ".", -1)
   172  	}
   173  
   174  	if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == sym.STEXT {
   175  		// When dynamically linking, we want references to functions defined
   176  		// in this module to always be to the function object, not to the
   177  		// PLT. We force this by writing an additional local symbol for every
   178  		// global function symbol and making all relocations against the
   179  		// global symbol refer to this local symbol instead (see
   180  		// (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the
   181  		// ELF linker -Bsymbolic-functions option, but that is buggy on
   182  		// several platforms.
   183  		putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other)
   184  		x.LocalElfsym = int32(numelfsym)
   185  		numelfsym++
   186  		return
   187  	} else if bind != elfbind {
   188  		return
   189  	}
   190  
   191  	putelfsyment(ctxt.Out, putelfstr(s), addr, size, bind<<4|typ&0xf, elfshnum, other)
   192  	x.Elfsym = int32(numelfsym)
   193  	numelfsym++
   194  }
   195  
   196  func putelfsectionsym(out *OutBuf, s *sym.Symbol, shndx int) {
   197  	putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
   198  	s.Elfsym = int32(numelfsym)
   199  	numelfsym++
   200  }
   201  
   202  func Asmelfsym(ctxt *Link) {
   203  	// the first symbol entry is reserved
   204  	putelfsyment(ctxt.Out, 0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
   205  
   206  	dwarfaddelfsectionsyms(ctxt)
   207  
   208  	// Some linkers will add a FILE sym if one is not present.
   209  	// Avoid having the working directory inserted into the symbol table.
   210  	// It is added with a name to avoid problems with external linking
   211  	// encountered on some versions of Solaris. See issue #14957.
   212  	putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
   213  	numelfsym++
   214  
   215  	elfbind = STB_LOCAL
   216  	genasmsym(ctxt, putelfsym)
   217  
   218  	elfbind = STB_GLOBAL
   219  	elfglobalsymndx = numelfsym
   220  	genasmsym(ctxt, putelfsym)
   221  }
   222  
   223  func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64, go_ *sym.Symbol) {
   224  	t := int(typ)
   225  	switch typ {
   226  	case TextSym, DataSym, BSSSym:
   227  		if x.Version != 0 {
   228  			t += 'a' - 'A'
   229  		}
   230  		fallthrough
   231  
   232  	case AutoSym, ParamSym, FrameSym:
   233  		l := 4
   234  		if ctxt.HeadType == objabi.Hplan9 && ctxt.Arch.Family == sys.AMD64 && !Flag8 {
   235  			ctxt.Out.Write32b(uint32(addr >> 32))
   236  			l = 8
   237  		}
   238  
   239  		ctxt.Out.Write32b(uint32(addr))
   240  		ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */
   241  
   242  		ctxt.Out.WriteString(s)
   243  		ctxt.Out.Write8(0)
   244  
   245  		Symsize += int32(l) + 1 + int32(len(s)) + 1
   246  
   247  	default:
   248  		return
   249  	}
   250  }
   251  
   252  func Asmplan9sym(ctxt *Link) {
   253  	genasmsym(ctxt, putplan9sym)
   254  }
   255  
   256  var symt *sym.Symbol
   257  
   258  type byPkg []*sym.Library
   259  
   260  func (libs byPkg) Len() int {
   261  	return len(libs)
   262  }
   263  
   264  func (libs byPkg) Less(a, b int) bool {
   265  	return libs[a].Pkg < libs[b].Pkg
   266  }
   267  
   268  func (libs byPkg) Swap(a, b int) {
   269  	libs[a], libs[b] = libs[b], libs[a]
   270  }
   271  
   272  // Create a table with information on the text sections.
   273  
   274  func textsectionmap(ctxt *Link) uint32 {
   275  
   276  	t := ctxt.Syms.Lookup("runtime.textsectionmap", 0)
   277  	t.Type = sym.SRODATA
   278  	t.Attr |= sym.AttrReachable
   279  	nsections := int64(0)
   280  
   281  	for _, sect := range Segtext.Sections {
   282  		if sect.Name == ".text" {
   283  			nsections++
   284  		} else {
   285  			break
   286  		}
   287  	}
   288  	t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize))
   289  
   290  	off := int64(0)
   291  	n := 0
   292  
   293  	// The vaddr for each text section is the difference between the section's
   294  	// Vaddr and the Vaddr for the first text section as determined at compile
   295  	// time.
   296  
   297  	// The symbol for the first text section is named runtime.text as before.
   298  	// Additional text sections are named runtime.text.n where n is the
   299  	// order of creation starting with 1. These symbols provide the section's
   300  	// address after relocation by the linker.
   301  
   302  	textbase := Segtext.Sections[0].Vaddr
   303  	for _, sect := range Segtext.Sections {
   304  		if sect.Name != ".text" {
   305  			break
   306  		}
   307  		off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase)
   308  		off = t.SetUint(ctxt.Arch, off, sect.Length)
   309  		if n == 0 {
   310  			s := ctxt.Syms.ROLookup("runtime.text", 0)
   311  			if s == nil {
   312  				Errorf(nil, "Unable to find symbol runtime.text\n")
   313  			}
   314  			off = t.SetAddr(ctxt.Arch, off, s)
   315  
   316  		} else {
   317  			s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
   318  			if s == nil {
   319  				Errorf(nil, "Unable to find symbol runtime.text.%d\n", n)
   320  			}
   321  			off = t.SetAddr(ctxt.Arch, off, s)
   322  		}
   323  		n++
   324  	}
   325  	return uint32(n)
   326  }
   327  
   328  func (ctxt *Link) symtab() {
   329  	dosymtype(ctxt)
   330  
   331  	// Define these so that they'll get put into the symbol table.
   332  	// data.c:/^address will provide the actual values.
   333  	ctxt.xdefine("runtime.text", sym.STEXT, 0)
   334  
   335  	ctxt.xdefine("runtime.etext", sym.STEXT, 0)
   336  	ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
   337  	ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
   338  	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
   339  	ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
   340  	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
   341  	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
   342  	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
   343  	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
   344  	ctxt.xdefine("runtime.data", sym.SDATA, 0)
   345  	ctxt.xdefine("runtime.edata", sym.SDATA, 0)
   346  	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
   347  	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
   348  	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
   349  	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
   350  	ctxt.xdefine("runtime.end", sym.SBSS, 0)
   351  	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   352  	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
   353  
   354  	// garbage collection symbols
   355  	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
   356  
   357  	s.Type = sym.SRODATA
   358  	s.Size = 0
   359  	s.Attr |= sym.AttrReachable
   360  	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   361  
   362  	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
   363  	s.Type = sym.SRODATA
   364  	s.Size = 0
   365  	s.Attr |= sym.AttrReachable
   366  	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   367  
   368  	// pseudo-symbols to mark locations of type, string, and go string data.
   369  	var symtype *sym.Symbol
   370  	var symtyperel *sym.Symbol
   371  	if !ctxt.DynlinkingGo() {
   372  		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   373  			s = ctxt.Syms.Lookup("type.*", 0)
   374  
   375  			s.Type = sym.STYPE
   376  			s.Size = 0
   377  			s.Attr |= sym.AttrReachable
   378  			symtype = s
   379  
   380  			s = ctxt.Syms.Lookup("typerel.*", 0)
   381  
   382  			s.Type = sym.STYPERELRO
   383  			s.Size = 0
   384  			s.Attr |= sym.AttrReachable
   385  			symtyperel = s
   386  		} else {
   387  			s = ctxt.Syms.Lookup("type.*", 0)
   388  
   389  			s.Type = sym.STYPE
   390  			s.Size = 0
   391  			s.Attr |= sym.AttrReachable
   392  			symtype = s
   393  			symtyperel = s
   394  		}
   395  	}
   396  
   397  	groupSym := func(name string, t sym.SymKind) *sym.Symbol {
   398  		s := ctxt.Syms.Lookup(name, 0)
   399  		s.Type = t
   400  		s.Size = 0
   401  		s.Attr |= sym.AttrLocal | sym.AttrReachable
   402  		return s
   403  	}
   404  	var (
   405  		symgostring = groupSym("go.string.*", sym.SGOSTRING)
   406  		symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
   407  		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   408  	)
   409  
   410  	var symgofuncrel *sym.Symbol
   411  	if !ctxt.DynlinkingGo() {
   412  		if ctxt.UseRelro() {
   413  			symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
   414  		} else {
   415  			symgofuncrel = symgofunc
   416  		}
   417  	}
   418  
   419  	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   420  	symitablink.Type = sym.SITABLINK
   421  
   422  	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   423  	symt.Attr |= sym.AttrLocal
   424  	symt.Type = sym.SSYMTAB
   425  	symt.Size = 0
   426  	symt.Attr |= sym.AttrReachable
   427  
   428  	nitablinks := 0
   429  
   430  	// assign specific types so that they sort together.
   431  	// within a type they sort by size, so the .* symbols
   432  	// just defined above will be first.
   433  	// hide the specific symbols.
   434  	for _, s := range ctxt.Syms.Allsym {
   435  		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
   436  			continue
   437  		}
   438  
   439  		switch {
   440  		case strings.HasPrefix(s.Name, "type."):
   441  			if !ctxt.DynlinkingGo() {
   442  				s.Attr |= sym.AttrNotInSymbolTable
   443  			}
   444  			if ctxt.UseRelro() {
   445  				s.Type = sym.STYPERELRO
   446  				s.Outer = symtyperel
   447  			} else {
   448  				s.Type = sym.STYPE
   449  				s.Outer = symtype
   450  			}
   451  
   452  		case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro():
   453  			// Keep go.importpath symbols in the same section as types and
   454  			// names, as they can be referred to by a section offset.
   455  			s.Type = sym.STYPERELRO
   456  
   457  		case strings.HasPrefix(s.Name, "go.itablink."):
   458  			nitablinks++
   459  			s.Type = sym.SITABLINK
   460  			s.Attr |= sym.AttrNotInSymbolTable
   461  			s.Outer = symitablink
   462  
   463  		case strings.HasPrefix(s.Name, "go.string."):
   464  			s.Type = sym.SGOSTRING
   465  			s.Attr |= sym.AttrNotInSymbolTable
   466  			s.Outer = symgostring
   467  
   468  		case strings.HasPrefix(s.Name, "runtime.gcbits."):
   469  			s.Type = sym.SGCBITS
   470  			s.Attr |= sym.AttrNotInSymbolTable
   471  			s.Outer = symgcbits
   472  
   473  		case strings.HasSuffix(s.Name, "·f"):
   474  			if !ctxt.DynlinkingGo() {
   475  				s.Attr |= sym.AttrNotInSymbolTable
   476  			}
   477  			if ctxt.UseRelro() {
   478  				s.Type = sym.SGOFUNCRELRO
   479  				s.Outer = symgofuncrel
   480  			} else {
   481  				s.Type = sym.SGOFUNC
   482  				s.Outer = symgofunc
   483  			}
   484  
   485  		case strings.HasPrefix(s.Name, "gcargs."),
   486  			strings.HasPrefix(s.Name, "gclocals."),
   487  			strings.HasPrefix(s.Name, "gclocals·"),
   488  			strings.HasPrefix(s.Name, "inltree."):
   489  			s.Type = sym.SGOFUNC
   490  			s.Attr |= sym.AttrNotInSymbolTable
   491  			s.Outer = symgofunc
   492  			s.Align = 4
   493  			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   494  		}
   495  	}
   496  
   497  	if ctxt.BuildMode == BuildModeShared {
   498  		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   499  		abihashgostr.Attr |= sym.AttrReachable
   500  		abihashgostr.Type = sym.SRODATA
   501  		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   502  		abihashgostr.AddAddr(ctxt.Arch, hashsym)
   503  		abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
   504  	}
   505  	if ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
   506  		for _, l := range ctxt.Library {
   507  			s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
   508  			s.Attr |= sym.AttrReachable
   509  			s.Type = sym.SRODATA
   510  			s.Size = int64(len(l.Hash))
   511  			s.P = []byte(l.Hash)
   512  			str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
   513  			str.Attr |= sym.AttrReachable
   514  			str.Type = sym.SRODATA
   515  			str.AddAddr(ctxt.Arch, s)
   516  			str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
   517  		}
   518  	}
   519  
   520  	nsections := textsectionmap(ctxt)
   521  
   522  	// Information about the layout of the executable image for the
   523  	// runtime to use. Any changes here must be matched by changes to
   524  	// the definition of moduledata in runtime/symtab.go.
   525  	// This code uses several global variables that are set by pcln.go:pclntab.
   526  	moduledata := ctxt.Moduledata
   527  	// The pclntab slice
   528  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
   529  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   530  	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   531  	// The ftab slice
   532  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   533  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   534  	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   535  	// The filetab slice
   536  	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   537  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   538  	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   539  	// findfunctab
   540  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   541  	// minpc, maxpc
   542  	moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
   543  	moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size)
   544  	// pointers to specific parts of the module
   545  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
   546  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
   547  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   548  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   549  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
   550  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
   551  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
   552  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
   553  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   554  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   555  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
   556  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
   557  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
   558  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
   559  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
   560  
   561  	// text section information
   562  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   563  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   564  	moduledata.AddUint(ctxt.Arch, uint64(nsections))
   565  
   566  	// The typelinks slice
   567  	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   568  	ntypelinks := uint64(typelinkSym.Size) / 4
   569  	moduledata.AddAddr(ctxt.Arch, typelinkSym)
   570  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   571  	moduledata.AddUint(ctxt.Arch, ntypelinks)
   572  	// The itablinks slice
   573  	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0))
   574  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   575  	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   576  	// The ptab slice
   577  	if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
   578  		ptab.Attr |= sym.AttrLocal
   579  		ptab.Type = sym.SRODATA
   580  
   581  		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   582  		moduledata.AddAddr(ctxt.Arch, ptab)
   583  		moduledata.AddUint(ctxt.Arch, nentries)
   584  		moduledata.AddUint(ctxt.Arch, nentries)
   585  	} else {
   586  		moduledata.AddUint(ctxt.Arch, 0)
   587  		moduledata.AddUint(ctxt.Arch, 0)
   588  		moduledata.AddUint(ctxt.Arch, 0)
   589  	}
   590  	if ctxt.BuildMode == BuildModePlugin {
   591  		addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   592  
   593  		pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
   594  		pkghashes.Attr |= sym.AttrReachable
   595  		pkghashes.Attr |= sym.AttrLocal
   596  		pkghashes.Type = sym.SRODATA
   597  
   598  		for i, l := range ctxt.Library {
   599  			// pkghashes[i].name
   600  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   601  			// pkghashes[i].linktimehash
   602  			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
   603  			// pkghashes[i].runtimehash
   604  			hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
   605  			pkghashes.AddAddr(ctxt.Arch, hash)
   606  		}
   607  		moduledata.AddAddr(ctxt.Arch, pkghashes)
   608  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   609  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   610  	} else {
   611  		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   612  		moduledata.AddUint(ctxt.Arch, 0)
   613  		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   614  		moduledata.AddUint(ctxt.Arch, 0)
   615  		moduledata.AddUint(ctxt.Arch, 0)
   616  	}
   617  	if len(ctxt.Shlibs) > 0 {
   618  		thismodulename := filepath.Base(*flagOutfile)
   619  		switch ctxt.BuildMode {
   620  		case BuildModeExe, BuildModePIE:
   621  			// When linking an executable, outfile is just "a.out". Make
   622  			// it something slightly more comprehensible.
   623  			thismodulename = "the executable"
   624  		}
   625  		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   626  
   627  		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   628  		modulehashes.Attr |= sym.AttrReachable
   629  		modulehashes.Attr |= sym.AttrLocal
   630  		modulehashes.Type = sym.SRODATA
   631  
   632  		for i, shlib := range ctxt.Shlibs {
   633  			// modulehashes[i].modulename
   634  			modulename := filepath.Base(shlib.Path)
   635  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   636  
   637  			// modulehashes[i].linktimehash
   638  			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   639  
   640  			// modulehashes[i].runtimehash
   641  			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   642  			abihash.Attr |= sym.AttrReachable
   643  			modulehashes.AddAddr(ctxt.Arch, abihash)
   644  		}
   645  
   646  		moduledata.AddAddr(ctxt.Arch, modulehashes)
   647  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   648  		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   649  	} else {
   650  		moduledata.AddUint(ctxt.Arch, 0) // modulename
   651  		moduledata.AddUint(ctxt.Arch, 0)
   652  		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   653  		moduledata.AddUint(ctxt.Arch, 0)
   654  		moduledata.AddUint(ctxt.Arch, 0)
   655  	}
   656  
   657  	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   658  	if hasmain {
   659  		moduledata.AddUint8(1)
   660  	} else {
   661  		moduledata.AddUint8(0)
   662  	}
   663  
   664  	// The rest of moduledata is zero initialized.
   665  	// When linking an object that does not contain the runtime we are
   666  	// creating the moduledata from scratch and it does not have a
   667  	// compiler-provided size, so read it from the type data.
   668  	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   669  	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   670  	moduledata.Grow(moduledata.Size)
   671  
   672  	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   673  	if lastmoduledatap.Type != sym.SDYNIMPORT {
   674  		lastmoduledatap.Type = sym.SNOPTRDATA
   675  		lastmoduledatap.Size = 0 // overwrite existing value
   676  		lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
   677  	}
   678  }
   679  

View as plain text