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