...

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

     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.IsFileLocal() || 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.IsFileLocal() {
   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		switch ctxt.BuildMode {
   330		case BuildModeCArchive, BuildModeCShared:
   331			for _, s := range ctxt.Syms.Allsym {
   332				// Create a new entry in the .init_array section that points to the
   333				// library initializer function.
   334				if s.Name == *flagEntrySymbol && ctxt.HeadType != objabi.Haix {
   335					addinitarrdata(ctxt, s)
   336				}
   337			}
   338		}
   339	
   340		// Define these so that they'll get put into the symbol table.
   341		// data.c:/^address will provide the actual values.
   342		ctxt.xdefine("runtime.text", sym.STEXT, 0)
   343	
   344		ctxt.xdefine("runtime.etext", sym.STEXT, 0)
   345		ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
   346		ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
   347		ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
   348		ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
   349		ctxt.xdefine("runtime.types", sym.SRODATA, 0)
   350		ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
   351		ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
   352		ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
   353		ctxt.xdefine("runtime.data", sym.SDATA, 0)
   354		ctxt.xdefine("runtime.edata", sym.SDATA, 0)
   355		ctxt.xdefine("runtime.bss", sym.SBSS, 0)
   356		ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
   357		ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
   358		ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
   359		ctxt.xdefine("runtime.end", sym.SBSS, 0)
   360		ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
   361		ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
   362	
   363		// garbage collection symbols
   364		s := ctxt.Syms.Lookup("runtime.gcdata", 0)
   365	
   366		s.Type = sym.SRODATA
   367		s.Size = 0
   368		s.Attr |= sym.AttrReachable
   369		ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
   370	
   371		s = ctxt.Syms.Lookup("runtime.gcbss", 0)
   372		s.Type = sym.SRODATA
   373		s.Size = 0
   374		s.Attr |= sym.AttrReachable
   375		ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
   376	
   377		// pseudo-symbols to mark locations of type, string, and go string data.
   378		var symtype *sym.Symbol
   379		var symtyperel *sym.Symbol
   380		if !ctxt.DynlinkingGo() {
   381			if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
   382				s = ctxt.Syms.Lookup("type.*", 0)
   383	
   384				s.Type = sym.STYPE
   385				s.Size = 0
   386				s.Attr |= sym.AttrReachable
   387				symtype = s
   388	
   389				s = ctxt.Syms.Lookup("typerel.*", 0)
   390	
   391				s.Type = sym.STYPERELRO
   392				s.Size = 0
   393				s.Attr |= sym.AttrReachable
   394				symtyperel = s
   395			} else {
   396				s = ctxt.Syms.Lookup("type.*", 0)
   397	
   398				s.Type = sym.STYPE
   399				s.Size = 0
   400				s.Attr |= sym.AttrReachable
   401				symtype = s
   402				symtyperel = s
   403			}
   404		}
   405	
   406		groupSym := func(name string, t sym.SymKind) *sym.Symbol {
   407			s := ctxt.Syms.Lookup(name, 0)
   408			s.Type = t
   409			s.Size = 0
   410			s.Attr |= sym.AttrLocal | sym.AttrReachable
   411			return s
   412		}
   413		var (
   414			symgostring = groupSym("go.string.*", sym.SGOSTRING)
   415			symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
   416			symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
   417		)
   418	
   419		var symgofuncrel *sym.Symbol
   420		if !ctxt.DynlinkingGo() {
   421			if ctxt.UseRelro() {
   422				symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
   423			} else {
   424				symgofuncrel = symgofunc
   425			}
   426		}
   427	
   428		symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
   429		symitablink.Type = sym.SITABLINK
   430	
   431		symt = ctxt.Syms.Lookup("runtime.symtab", 0)
   432		symt.Attr |= sym.AttrLocal
   433		symt.Type = sym.SSYMTAB
   434		symt.Size = 0
   435		symt.Attr |= sym.AttrReachable
   436	
   437		nitablinks := 0
   438	
   439		// assign specific types so that they sort together.
   440		// within a type they sort by size, so the .* symbols
   441		// just defined above will be first.
   442		// hide the specific symbols.
   443		for _, s := range ctxt.Syms.Allsym {
   444			if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
   445				s.Attr |= sym.AttrNotInSymbolTable
   446			}
   447	
   448			if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
   449				continue
   450			}
   451	
   452			switch {
   453			case strings.HasPrefix(s.Name, "type."):
   454				if !ctxt.DynlinkingGo() {
   455					s.Attr |= sym.AttrNotInSymbolTable
   456				}
   457				if ctxt.UseRelro() {
   458					s.Type = sym.STYPERELRO
   459					s.Outer = symtyperel
   460				} else {
   461					s.Type = sym.STYPE
   462					s.Outer = symtype
   463				}
   464	
   465			case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro():
   466				// Keep go.importpath symbols in the same section as types and
   467				// names, as they can be referred to by a section offset.
   468				s.Type = sym.STYPERELRO
   469	
   470			case strings.HasPrefix(s.Name, "go.itablink."):
   471				nitablinks++
   472				s.Type = sym.SITABLINK
   473				s.Attr |= sym.AttrNotInSymbolTable
   474				s.Outer = symitablink
   475	
   476			case strings.HasPrefix(s.Name, "go.string."):
   477				s.Type = sym.SGOSTRING
   478				s.Attr |= sym.AttrNotInSymbolTable
   479				s.Outer = symgostring
   480	
   481			case strings.HasPrefix(s.Name, "runtime.gcbits."):
   482				s.Type = sym.SGCBITS
   483				s.Attr |= sym.AttrNotInSymbolTable
   484				s.Outer = symgcbits
   485	
   486			case strings.HasSuffix(s.Name, "·f"):
   487				if !ctxt.DynlinkingGo() {
   488					s.Attr |= sym.AttrNotInSymbolTable
   489				}
   490				if ctxt.UseRelro() {
   491					s.Type = sym.SGOFUNCRELRO
   492					s.Outer = symgofuncrel
   493				} else {
   494					s.Type = sym.SGOFUNC
   495					s.Outer = symgofunc
   496				}
   497	
   498			case strings.HasPrefix(s.Name, "gcargs."),
   499				strings.HasPrefix(s.Name, "gclocals."),
   500				strings.HasPrefix(s.Name, "gclocals·"),
   501				strings.HasPrefix(s.Name, "inltree."):
   502				s.Type = sym.SGOFUNC
   503				s.Attr |= sym.AttrNotInSymbolTable
   504				s.Outer = symgofunc
   505				s.Align = 4
   506				liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
   507			}
   508		}
   509	
   510		if ctxt.BuildMode == BuildModeShared {
   511			abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
   512			abihashgostr.Attr |= sym.AttrReachable
   513			abihashgostr.Type = sym.SRODATA
   514			hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
   515			abihashgostr.AddAddr(ctxt.Arch, hashsym)
   516			abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
   517		}
   518		if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   519			for _, l := range ctxt.Library {
   520				s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
   521				s.Attr |= sym.AttrReachable
   522				s.Type = sym.SRODATA
   523				s.Size = int64(len(l.Hash))
   524				s.P = []byte(l.Hash)
   525				str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
   526				str.Attr |= sym.AttrReachable
   527				str.Type = sym.SRODATA
   528				str.AddAddr(ctxt.Arch, s)
   529				str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
   530			}
   531		}
   532	
   533		nsections := textsectionmap(ctxt)
   534	
   535		// Information about the layout of the executable image for the
   536		// runtime to use. Any changes here must be matched by changes to
   537		// the definition of moduledata in runtime/symtab.go.
   538		// This code uses several global variables that are set by pcln.go:pclntab.
   539		moduledata := ctxt.Moduledata
   540		// The pclntab slice
   541		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
   542		moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   543		moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
   544		// The ftab slice
   545		moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
   546		moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   547		moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
   548		// The filetab slice
   549		moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
   550		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   551		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
   552		// findfunctab
   553		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
   554		// minpc, maxpc
   555		moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
   556		moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size)
   557		// pointers to specific parts of the module
   558		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
   559		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
   560		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
   561		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
   562		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
   563		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
   564		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
   565		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
   566		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
   567		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
   568		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
   569		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
   570		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
   571		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
   572		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
   573	
   574		if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
   575			// Add R_REF relocation to prevent ld's garbage collection of
   576			// runtime.rodata, runtime.erodata and runtime.epclntab.
   577			addRef := func(name string) {
   578				r := moduledata.AddRel()
   579				r.Sym = ctxt.Syms.Lookup(name, 0)
   580				r.Type = objabi.R_XCOFFREF
   581				r.Siz = uint8(ctxt.Arch.PtrSize)
   582			}
   583			addRef("runtime.rodata")
   584			addRef("runtime.erodata")
   585			addRef("runtime.epclntab")
   586		}
   587	
   588		// text section information
   589		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
   590		moduledata.AddUint(ctxt.Arch, uint64(nsections))
   591		moduledata.AddUint(ctxt.Arch, uint64(nsections))
   592	
   593		// The typelinks slice
   594		typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
   595		ntypelinks := uint64(typelinkSym.Size) / 4
   596		moduledata.AddAddr(ctxt.Arch, typelinkSym)
   597		moduledata.AddUint(ctxt.Arch, ntypelinks)
   598		moduledata.AddUint(ctxt.Arch, ntypelinks)
   599		// The itablinks slice
   600		moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0))
   601		moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   602		moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
   603		// The ptab slice
   604		if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
   605			ptab.Attr |= sym.AttrLocal
   606			ptab.Type = sym.SRODATA
   607	
   608			nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
   609			moduledata.AddAddr(ctxt.Arch, ptab)
   610			moduledata.AddUint(ctxt.Arch, nentries)
   611			moduledata.AddUint(ctxt.Arch, nentries)
   612		} else {
   613			moduledata.AddUint(ctxt.Arch, 0)
   614			moduledata.AddUint(ctxt.Arch, 0)
   615			moduledata.AddUint(ctxt.Arch, 0)
   616		}
   617		if ctxt.BuildMode == BuildModePlugin {
   618			addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
   619	
   620			pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
   621			pkghashes.Attr |= sym.AttrReachable
   622			pkghashes.Attr |= sym.AttrLocal
   623			pkghashes.Type = sym.SRODATA
   624	
   625			for i, l := range ctxt.Library {
   626				// pkghashes[i].name
   627				addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
   628				// pkghashes[i].linktimehash
   629				addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
   630				// pkghashes[i].runtimehash
   631				hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
   632				pkghashes.AddAddr(ctxt.Arch, hash)
   633			}
   634			moduledata.AddAddr(ctxt.Arch, pkghashes)
   635			moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   636			moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
   637		} else {
   638			moduledata.AddUint(ctxt.Arch, 0) // pluginpath
   639			moduledata.AddUint(ctxt.Arch, 0)
   640			moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
   641			moduledata.AddUint(ctxt.Arch, 0)
   642			moduledata.AddUint(ctxt.Arch, 0)
   643		}
   644		if len(ctxt.Shlibs) > 0 {
   645			thismodulename := filepath.Base(*flagOutfile)
   646			switch ctxt.BuildMode {
   647			case BuildModeExe, BuildModePIE:
   648				// When linking an executable, outfile is just "a.out". Make
   649				// it something slightly more comprehensible.
   650				thismodulename = "the executable"
   651			}
   652			addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
   653	
   654			modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
   655			modulehashes.Attr |= sym.AttrReachable
   656			modulehashes.Attr |= sym.AttrLocal
   657			modulehashes.Type = sym.SRODATA
   658	
   659			for i, shlib := range ctxt.Shlibs {
   660				// modulehashes[i].modulename
   661				modulename := filepath.Base(shlib.Path)
   662				addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
   663	
   664				// modulehashes[i].linktimehash
   665				addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
   666	
   667				// modulehashes[i].runtimehash
   668				abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
   669				abihash.Attr |= sym.AttrReachable
   670				modulehashes.AddAddr(ctxt.Arch, abihash)
   671			}
   672	
   673			moduledata.AddAddr(ctxt.Arch, modulehashes)
   674			moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   675			moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
   676		} else {
   677			moduledata.AddUint(ctxt.Arch, 0) // modulename
   678			moduledata.AddUint(ctxt.Arch, 0)
   679			moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
   680			moduledata.AddUint(ctxt.Arch, 0)
   681			moduledata.AddUint(ctxt.Arch, 0)
   682		}
   683	
   684		hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
   685		if hasmain {
   686			moduledata.AddUint8(1)
   687		} else {
   688			moduledata.AddUint8(0)
   689		}
   690	
   691		// The rest of moduledata is zero initialized.
   692		// When linking an object that does not contain the runtime we are
   693		// creating the moduledata from scratch and it does not have a
   694		// compiler-provided size, so read it from the type data.
   695		moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
   696		moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype)
   697		moduledata.Grow(moduledata.Size)
   698	
   699		lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
   700		if lastmoduledatap.Type != sym.SDYNIMPORT {
   701			lastmoduledatap.Type = sym.SNOPTRDATA
   702			lastmoduledatap.Size = 0 // overwrite existing value
   703			lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
   704		}
   705	}
   706	
   707	func isStaticTemp(name string) bool {
   708		if i := strings.LastIndex(name, "/"); i >= 0 {
   709			name = name[i:]
   710		}
   711		return strings.Contains(name, "..stmp_")
   712	}
   713	

View as plain text