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