1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ld
6
7import (
8	"cmd/internal/notsha256"
9	"cmd/internal/objabi"
10	"cmd/internal/sys"
11	"cmd/link/internal/loader"
12	"cmd/link/internal/sym"
13	"debug/elf"
14	"encoding/binary"
15	"encoding/hex"
16	"fmt"
17	"internal/buildcfg"
18	"os"
19	"path/filepath"
20	"runtime"
21	"sort"
22	"strings"
23)
24
25/*
26 * Derived from:
27 * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
28 * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
29 * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
30 * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
31 * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
32 * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
33 * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
34 * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
35 * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
36 *
37 * Copyright (c) 1996-1998 John D. Polstra.  All rights reserved.
38 * Copyright (c) 2001 David E. O'Brien
39 * Portions Copyright 2009 The Go Authors. All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 *    notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 *    notice, this list of conditions and the following disclaimer in the
48 *    documentation and/or other materials provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 */
63
64/*
65 * ELF definitions that are independent of architecture or word size.
66 */
67
68/*
69 * Note header.  The ".note" section contains an array of notes.  Each
70 * begins with this header, aligned to a word boundary.  Immediately
71 * following the note header is n_namesz bytes of name, padded to the
72 * next word boundary.  Then comes n_descsz bytes of descriptor, again
73 * padded to a word boundary.  The values of n_namesz and n_descsz do
74 * not include the padding.
75 */
76type elfNote struct {
77	nNamesz uint32
78	nDescsz uint32
79	nType   uint32
80}
81
82/* For accessing the fields of r_info. */
83
84/* For constructing r_info from field values. */
85
86/*
87 * Relocation types.
88 */
89const (
90	ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
91)
92
93/*
94 * Symbol table entries.
95 */
96
97/* For accessing the fields of st_info. */
98
99/* For constructing st_info from field values. */
100
101/* For accessing the fields of st_other. */
102
103/*
104 * ELF header.
105 */
106type ElfEhdr elf.Header64
107
108/*
109 * Section header.
110 */
111type ElfShdr struct {
112	elf.Section64
113	shnum elf.SectionIndex
114}
115
116/*
117 * Program header.
118 */
119type ElfPhdr elf.ProgHeader
120
121/* For accessing the fields of r_info. */
122
123/* For constructing r_info from field values. */
124
125/*
126 * Symbol table entries.
127 */
128
129/* For accessing the fields of st_info. */
130
131/* For constructing st_info from field values. */
132
133/* For accessing the fields of st_other. */
134
135/*
136 * Go linker interface
137 */
138const (
139	ELF64HDRSIZE  = 64
140	ELF64PHDRSIZE = 56
141	ELF64SHDRSIZE = 64
142	ELF64RELSIZE  = 16
143	ELF64RELASIZE = 24
144	ELF64SYMSIZE  = 24
145	ELF32HDRSIZE  = 52
146	ELF32PHDRSIZE = 32
147	ELF32SHDRSIZE = 40
148	ELF32SYMSIZE  = 16
149	ELF32RELSIZE  = 8
150)
151
152/*
153 * The interface uses the 64-bit structures always,
154 * to avoid code duplication.  The writers know how to
155 * marshal a 32-bit representation from the 64-bit structure.
156 */
157
158var elfstrdat, elfshstrdat []byte
159
160/*
161 * Total amount of space to reserve at the start of the file
162 * for Header, PHeaders, SHeaders, and interp.
163 * May waste some.
164 * On FreeBSD, cannot be larger than a page.
165 */
166const (
167	ELFRESERVE = 4096
168)
169
170/*
171 * We use the 64-bit data structures on both 32- and 64-bit machines
172 * in order to write the code just once.  The 64-bit data structure is
173 * written in the 32-bit format on the 32-bit machines.
174 */
175const (
176	NSECT = 400
177)
178
179var (
180	Nelfsym = 1
181
182	elf64 bool
183	// Either ".rel" or ".rela" depending on which type of relocation the
184	// target platform uses.
185	elfRelType string
186
187	ehdr ElfEhdr
188	phdr [NSECT]*ElfPhdr
189	shdr [NSECT]*ElfShdr
190
191	interp string
192)
193
194// ELFArch includes target-specific hooks for ELF targets.
195// This is initialized by the target-specific Init function
196// called by the linker's main function in cmd/link/main.go.
197type ELFArch struct {
198	// TODO: Document these fields.
199
200	Androiddynld   string
201	Linuxdynld     string
202	LinuxdynldMusl string
203	Freebsddynld   string
204	Netbsddynld    string
205	Openbsddynld   string
206	Dragonflydynld string
207	Solarisdynld   string
208
209	Reloc1    func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int, int64) bool
210	RelocSize uint32 // size of an ELF relocation record, must match Reloc1.
211	SetupPLT  func(ctxt *Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
212
213	// DynamicReadOnly can be set to true to make the .dynamic
214	// section read-only. By default it is writable.
215	// This is used by MIPS targets.
216	DynamicReadOnly bool
217}
218
219type Elfstring struct {
220	s   string
221	off int
222}
223
224var elfstr [100]Elfstring
225
226var nelfstr int
227
228var buildinfo []byte
229
230/*
231Initialize the global variable that describes the ELF header. It will be updated as
232we write section and prog headers.
233*/
234func Elfinit(ctxt *Link) {
235	ctxt.IsELF = true
236
237	if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
238		elfRelType = ".rela"
239	} else {
240		elfRelType = ".rel"
241	}
242
243	switch ctxt.Arch.Family {
244	// 64-bit architectures
245	case sys.PPC64, sys.S390X:
246		if ctxt.Arch.ByteOrder == binary.BigEndian && ctxt.HeadType != objabi.Hopenbsd {
247			ehdr.Flags = 1 /* Version 1 ABI */
248		} else {
249			ehdr.Flags = 2 /* Version 2 ABI */
250		}
251		fallthrough
252	case sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.RISCV64:
253		if ctxt.Arch.Family == sys.MIPS64 {
254			ehdr.Flags = 0x20000004 /* MIPS 3 CPIC */
255		}
256		if ctxt.Arch.Family == sys.Loong64 {
257			ehdr.Flags = 0x43 /* DOUBLE_FLOAT, OBJABI_V1 */
258		}
259		if ctxt.Arch.Family == sys.RISCV64 {
260			ehdr.Flags = 0x4 /* RISCV Float ABI Double */
261		}
262		elf64 = true
263
264		ehdr.Phoff = ELF64HDRSIZE      /* Must be ELF64HDRSIZE: first PHdr must follow ELF header */
265		ehdr.Shoff = ELF64HDRSIZE      /* Will move as we add PHeaders */
266		ehdr.Ehsize = ELF64HDRSIZE     /* Must be ELF64HDRSIZE */
267		ehdr.Phentsize = ELF64PHDRSIZE /* Must be ELF64PHDRSIZE */
268		ehdr.Shentsize = ELF64SHDRSIZE /* Must be ELF64SHDRSIZE */
269
270	// 32-bit architectures
271	case sys.ARM, sys.MIPS:
272		if ctxt.Arch.Family == sys.ARM {
273			// we use EABI on linux/arm, freebsd/arm, netbsd/arm.
274			if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd {
275				// We set a value here that makes no indication of which
276				// float ABI the object uses, because this is information
277				// used by the dynamic linker to compare executables and
278				// shared libraries -- so it only matters for cgo calls, and
279				// the information properly comes from the object files
280				// produced by the host C compiler. parseArmAttributes in
281				// ldelf.go reads that information and updates this field as
282				// appropriate.
283				ehdr.Flags = 0x5000002 // has entry point, Version5 EABI
284			}
285		} else if ctxt.Arch.Family == sys.MIPS {
286			ehdr.Flags = 0x50001004 /* MIPS 32 CPIC O32*/
287		}
288		fallthrough
289	default:
290		ehdr.Phoff = ELF32HDRSIZE
291		/* Must be ELF32HDRSIZE: first PHdr must follow ELF header */
292		ehdr.Shoff = ELF32HDRSIZE      /* Will move as we add PHeaders */
293		ehdr.Ehsize = ELF32HDRSIZE     /* Must be ELF32HDRSIZE */
294		ehdr.Phentsize = ELF32PHDRSIZE /* Must be ELF32PHDRSIZE */
295		ehdr.Shentsize = ELF32SHDRSIZE /* Must be ELF32SHDRSIZE */
296	}
297}
298
299// Make sure PT_LOAD is aligned properly and
300// that there is no gap,
301// correct ELF loaders will do this implicitly,
302// but buggy ELF loaders like the one in some
303// versions of QEMU and UPX won't.
304func fixElfPhdr(e *ElfPhdr) {
305	frag := int(e.Vaddr & (e.Align - 1))
306
307	e.Off -= uint64(frag)
308	e.Vaddr -= uint64(frag)
309	e.Paddr -= uint64(frag)
310	e.Filesz += uint64(frag)
311	e.Memsz += uint64(frag)
312}
313
314func elf64phdr(out *OutBuf, e *ElfPhdr) {
315	if e.Type == elf.PT_LOAD {
316		fixElfPhdr(e)
317	}
318
319	out.Write32(uint32(e.Type))
320	out.Write32(uint32(e.Flags))
321	out.Write64(e.Off)
322	out.Write64(e.Vaddr)
323	out.Write64(e.Paddr)
324	out.Write64(e.Filesz)
325	out.Write64(e.Memsz)
326	out.Write64(e.Align)
327}
328
329func elf32phdr(out *OutBuf, e *ElfPhdr) {
330	if e.Type == elf.PT_LOAD {
331		fixElfPhdr(e)
332	}
333
334	out.Write32(uint32(e.Type))
335	out.Write32(uint32(e.Off))
336	out.Write32(uint32(e.Vaddr))
337	out.Write32(uint32(e.Paddr))
338	out.Write32(uint32(e.Filesz))
339	out.Write32(uint32(e.Memsz))
340	out.Write32(uint32(e.Flags))
341	out.Write32(uint32(e.Align))
342}
343
344func elf64shdr(out *OutBuf, e *ElfShdr) {
345	out.Write32(e.Name)
346	out.Write32(uint32(e.Type))
347	out.Write64(uint64(e.Flags))
348	out.Write64(e.Addr)
349	out.Write64(e.Off)
350	out.Write64(e.Size)
351	out.Write32(e.Link)
352	out.Write32(e.Info)
353	out.Write64(e.Addralign)
354	out.Write64(e.Entsize)
355}
356
357func elf32shdr(out *OutBuf, e *ElfShdr) {
358	out.Write32(e.Name)
359	out.Write32(uint32(e.Type))
360	out.Write32(uint32(e.Flags))
361	out.Write32(uint32(e.Addr))
362	out.Write32(uint32(e.Off))
363	out.Write32(uint32(e.Size))
364	out.Write32(e.Link)
365	out.Write32(e.Info)
366	out.Write32(uint32(e.Addralign))
367	out.Write32(uint32(e.Entsize))
368}
369
370func elfwriteshdrs(out *OutBuf) uint32 {
371	if elf64 {
372		for i := 0; i < int(ehdr.Shnum); i++ {
373			elf64shdr(out, shdr[i])
374		}
375		return uint32(ehdr.Shnum) * ELF64SHDRSIZE
376	}
377
378	for i := 0; i < int(ehdr.Shnum); i++ {
379		elf32shdr(out, shdr[i])
380	}
381	return uint32(ehdr.Shnum) * ELF32SHDRSIZE
382}
383
384func elfsetstring(ctxt *Link, s loader.Sym, str string, off int) {
385	if nelfstr >= len(elfstr) {
386		ctxt.Errorf(s, "too many elf strings")
387		errorexit()
388	}
389
390	elfstr[nelfstr].s = str
391	elfstr[nelfstr].off = off
392	nelfstr++
393}
394
395func elfwritephdrs(out *OutBuf) uint32 {
396	if elf64 {
397		for i := 0; i < int(ehdr.Phnum); i++ {
398			elf64phdr(out, phdr[i])
399		}
400		return uint32(ehdr.Phnum) * ELF64PHDRSIZE
401	}
402
403	for i := 0; i < int(ehdr.Phnum); i++ {
404		elf32phdr(out, phdr[i])
405	}
406	return uint32(ehdr.Phnum) * ELF32PHDRSIZE
407}
408
409func newElfPhdr() *ElfPhdr {
410	e := new(ElfPhdr)
411	if ehdr.Phnum >= NSECT {
412		Errorf(nil, "too many phdrs")
413	} else {
414		phdr[ehdr.Phnum] = e
415		ehdr.Phnum++
416	}
417	if elf64 {
418		ehdr.Shoff += ELF64PHDRSIZE
419	} else {
420		ehdr.Shoff += ELF32PHDRSIZE
421	}
422	return e
423}
424
425func newElfShdr(name int64) *ElfShdr {
426	e := new(ElfShdr)
427	e.Name = uint32(name)
428	e.shnum = elf.SectionIndex(ehdr.Shnum)
429	if ehdr.Shnum >= NSECT {
430		Errorf(nil, "too many shdrs")
431	} else {
432		shdr[ehdr.Shnum] = e
433		ehdr.Shnum++
434	}
435
436	return e
437}
438
439func getElfEhdr() *ElfEhdr {
440	return &ehdr
441}
442
443func elf64writehdr(out *OutBuf) uint32 {
444	out.Write(ehdr.Ident[:])
445	out.Write16(uint16(ehdr.Type))
446	out.Write16(uint16(ehdr.Machine))
447	out.Write32(uint32(ehdr.Version))
448	out.Write64(ehdr.Entry)
449	out.Write64(ehdr.Phoff)
450	out.Write64(ehdr.Shoff)
451	out.Write32(ehdr.Flags)
452	out.Write16(ehdr.Ehsize)
453	out.Write16(ehdr.Phentsize)
454	out.Write16(ehdr.Phnum)
455	out.Write16(ehdr.Shentsize)
456	out.Write16(ehdr.Shnum)
457	out.Write16(ehdr.Shstrndx)
458	return ELF64HDRSIZE
459}
460
461func elf32writehdr(out *OutBuf) uint32 {
462	out.Write(ehdr.Ident[:])
463	out.Write16(uint16(ehdr.Type))
464	out.Write16(uint16(ehdr.Machine))
465	out.Write32(uint32(ehdr.Version))
466	out.Write32(uint32(ehdr.Entry))
467	out.Write32(uint32(ehdr.Phoff))
468	out.Write32(uint32(ehdr.Shoff))
469	out.Write32(ehdr.Flags)
470	out.Write16(ehdr.Ehsize)
471	out.Write16(ehdr.Phentsize)
472	out.Write16(ehdr.Phnum)
473	out.Write16(ehdr.Shentsize)
474	out.Write16(ehdr.Shnum)
475	out.Write16(ehdr.Shstrndx)
476	return ELF32HDRSIZE
477}
478
479func elfwritehdr(out *OutBuf) uint32 {
480	if elf64 {
481		return elf64writehdr(out)
482	}
483	return elf32writehdr(out)
484}
485
486/* Taken directly from the definition document for ELF64. */
487func elfhash(name string) uint32 {
488	var h uint32
489	for i := 0; i < len(name); i++ {
490		h = (h << 4) + uint32(name[i])
491		if g := h & 0xf0000000; g != 0 {
492			h ^= g >> 24
493		}
494		h &= 0x0fffffff
495	}
496	return h
497}
498
499func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
500	Elfwritedynentsymplus(ctxt, s, tag, t, 0)
501}
502
503func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag elf.DynTag, val uint64) {
504	if elf64 {
505		s.AddUint64(arch, uint64(tag))
506		s.AddUint64(arch, val)
507	} else {
508		s.AddUint32(arch, uint32(tag))
509		s.AddUint32(arch, uint32(val))
510	}
511}
512
513func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym, add int64) {
514	if elf64 {
515		s.AddUint64(ctxt.Arch, uint64(tag))
516	} else {
517		s.AddUint32(ctxt.Arch, uint32(tag))
518	}
519	s.AddAddrPlus(ctxt.Arch, t, add)
520}
521
522func elfwritedynentsymsize(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
523	if elf64 {
524		s.AddUint64(ctxt.Arch, uint64(tag))
525	} else {
526		s.AddUint32(ctxt.Arch, uint32(tag))
527	}
528	s.AddSize(ctxt.Arch, t)
529}
530
531func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int {
532	interp = p
533	n := len(interp) + 1
534	sh.Addr = startva + resoff - uint64(n)
535	sh.Off = resoff - uint64(n)
536	sh.Size = uint64(n)
537
538	return n
539}
540
541func elfwriteinterp(out *OutBuf) int {
542	sh := elfshname(".interp")
543	out.SeekSet(int64(sh.Off))
544	out.WriteString(interp)
545	out.Write8(0)
546	return int(sh.Size)
547}
548
549// member of .gnu.attributes of MIPS for fpAbi
550const (
551	// No floating point is present in the module (default)
552	MIPS_FPABI_NONE = 0
553	// FP code in the module uses the FP32 ABI for a 32-bit ABI
554	MIPS_FPABI_ANY = 1
555	// FP code in the module only uses single precision ABI
556	MIPS_FPABI_SINGLE = 2
557	// FP code in the module uses soft-float ABI
558	MIPS_FPABI_SOFT = 3
559	// FP code in the module assumes an FPU with FR=1 and has 12
560	// callee-saved doubles. Historic, no longer supported.
561	MIPS_FPABI_HIST = 4
562	// FP code in the module uses the FPXX  ABI
563	MIPS_FPABI_FPXX = 5
564	// FP code in the module uses the FP64  ABI
565	MIPS_FPABI_FP64 = 6
566	// FP code in the module uses the FP64A ABI
567	MIPS_FPABI_FP64A = 7
568)
569
570func elfMipsAbiFlags(sh *ElfShdr, startva uint64, resoff uint64) int {
571	n := 24
572	sh.Addr = startva + resoff - uint64(n)
573	sh.Off = resoff - uint64(n)
574	sh.Size = uint64(n)
575	sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
576	sh.Flags = uint64(elf.SHF_ALLOC)
577
578	return n
579}
580
581// Layout is given by this C definition:
582//
583//	typedef struct
584//	{
585//	  /* Version of flags structure.  */
586//	  uint16_t version;
587//	  /* The level of the ISA: 1-5, 32, 64.  */
588//	  uint8_t isa_level;
589//	  /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise.  */
590//	  uint8_t isa_rev;
591//	  /* The size of general purpose registers.  */
592//	  uint8_t gpr_size;
593//	  /* The size of co-processor 1 registers.  */
594//	  uint8_t cpr1_size;
595//	  /* The size of co-processor 2 registers.  */
596//	  uint8_t cpr2_size;
597//	  /* The floating-point ABI.  */
598//	  uint8_t fp_abi;
599//	  /* Processor-specific extension.  */
600//	  uint32_t isa_ext;
601//	  /* Mask of ASEs used.  */
602//	  uint32_t ases;
603//	  /* Mask of general flags.  */
604//	  uint32_t flags1;
605//	  uint32_t flags2;
606//	} Elf_Internal_ABIFlags_v0;
607func elfWriteMipsAbiFlags(ctxt *Link) int {
608	sh := elfshname(".MIPS.abiflags")
609	ctxt.Out.SeekSet(int64(sh.Off))
610	ctxt.Out.Write16(0) // version
611	ctxt.Out.Write8(32) // isaLevel
612	ctxt.Out.Write8(1)  // isaRev
613	ctxt.Out.Write8(1)  // gprSize
614	ctxt.Out.Write8(1)  // cpr1Size
615	ctxt.Out.Write8(0)  // cpr2Size
616	if buildcfg.GOMIPS == "softfloat" {
617		ctxt.Out.Write8(MIPS_FPABI_SOFT) // fpAbi
618	} else {
619		// Go cannot make sure non odd-number-fpr is used (ie, in load a double from memory).
620		// So, we mark the object is MIPS I style paired float/double register scheme,
621		// aka MIPS_FPABI_ANY. If we mark the object as FPXX, the kernel may use FR=1 mode,
622		// then we meet some problem.
623		// Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
624		//       It is not for 'ANY'.
625		// TODO: switch to FPXX after be sure that no odd-number-fpr is used.
626		ctxt.Out.Write8(MIPS_FPABI_ANY) // fpAbi
627	}
628	ctxt.Out.Write32(0) // isaExt
629	ctxt.Out.Write32(0) // ases
630	ctxt.Out.Write32(0) // flags1
631	ctxt.Out.Write32(0) // flags2
632	return int(sh.Size)
633}
634
635func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sizes ...int) int {
636	n := resoff % 4
637	// if section contains multiple notes (as is the case with FreeBSD signature),
638	// multiple note sizes can be specified
639	for _, sz := range sizes {
640		n += 3*4 + uint64(sz)
641	}
642
643	sh.Type = uint32(elf.SHT_NOTE)
644	sh.Flags = uint64(elf.SHF_ALLOC)
645	sh.Addralign = 4
646	sh.Addr = startva + resoff - n
647	sh.Off = resoff - n
648	sh.Size = n - resoff%4
649
650	return int(n)
651}
652
653func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr {
654	sh := elfshname(str)
655
656	// Write Elf_Note header.
657	out.SeekSet(int64(sh.Off))
658
659	out.Write32(namesz)
660	out.Write32(descsz)
661	out.Write32(tag)
662
663	return sh
664}
665
666// NetBSD Signature (as per sys/exec_elf.h)
667const (
668	ELF_NOTE_NETBSD_NAMESZ  = 7
669	ELF_NOTE_NETBSD_DESCSZ  = 4
670	ELF_NOTE_NETBSD_TAG     = 1
671	ELF_NOTE_NETBSD_VERSION = 700000000 /* NetBSD 7.0 */
672)
673
674var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
675
676func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
677	n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
678	return elfnote(sh, startva, resoff, n)
679}
680
681func elfwritenetbsdsig(out *OutBuf) int {
682	// Write Elf_Note header.
683	sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG)
684
685	if sh == nil {
686		return 0
687	}
688
689	// Followed by NetBSD string and version.
690	out.Write(ELF_NOTE_NETBSD_NAME)
691	out.Write8(0)
692	out.Write32(ELF_NOTE_NETBSD_VERSION)
693
694	return int(sh.Size)
695}
696
697// The race detector can't handle ASLR (address space layout randomization).
698// ASLR is on by default for NetBSD, so we turn the ASLR off explicitly
699// using a magic elf Note when building race binaries.
700
701func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int {
702	n := int(Rnd(4, 4) + Rnd(4, 4))
703	return elfnote(sh, startva, resoff, n)
704}
705
706func elfwritenetbsdpax(out *OutBuf) int {
707	sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 /* length of PaX\x00 */, 4 /* length of flags */, 0x03 /* PaX type */)
708	if sh == nil {
709		return 0
710	}
711	out.Write([]byte("PaX\x00"))
712	out.Write32(0x20) // 0x20 = Force disable ASLR
713	return int(sh.Size)
714}
715
716// OpenBSD Signature
717const (
718	ELF_NOTE_OPENBSD_NAMESZ  = 8
719	ELF_NOTE_OPENBSD_DESCSZ  = 4
720	ELF_NOTE_OPENBSD_TAG     = 1
721	ELF_NOTE_OPENBSD_VERSION = 0
722)
723
724var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
725
726func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
727	n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
728	return elfnote(sh, startva, resoff, n)
729}
730
731func elfwriteopenbsdsig(out *OutBuf) int {
732	// Write Elf_Note header.
733	sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG)
734
735	if sh == nil {
736		return 0
737	}
738
739	// Followed by OpenBSD string and version.
740	out.Write(ELF_NOTE_OPENBSD_NAME)
741
742	out.Write32(ELF_NOTE_OPENBSD_VERSION)
743
744	return int(sh.Size)
745}
746
747// FreeBSD Signature (as per sys/elf_common.h)
748const (
749	ELF_NOTE_FREEBSD_NAMESZ            = 8
750	ELF_NOTE_FREEBSD_DESCSZ            = 4
751	ELF_NOTE_FREEBSD_ABI_TAG           = 1
752	ELF_NOTE_FREEBSD_NOINIT_TAG        = 2
753	ELF_NOTE_FREEBSD_FEATURE_CTL_TAG   = 4
754	ELF_NOTE_FREEBSD_VERSION           = 1203000 // 12.3-RELEASE
755	ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE = 0x1
756)
757
758const ELF_NOTE_FREEBSD_NAME = "FreeBSD\x00"
759
760func elffreebsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
761	n := ELF_NOTE_FREEBSD_NAMESZ + ELF_NOTE_FREEBSD_DESCSZ
762	// FreeBSD signature section contains 3 equally sized notes
763	return elfnote(sh, startva, resoff, n, n, n)
764}
765
766// elfwritefreebsdsig writes FreeBSD .note section.
767//
768// See https://www.netbsd.org/docs/kernel/elf-notes.html for the description of
769// a Note element format and
770// https://github.com/freebsd/freebsd-src/blob/main/sys/sys/elf_common.h#L790
771// for the FreeBSD-specific values.
772func elfwritefreebsdsig(out *OutBuf) int {
773	sh := elfshname(".note.tag")
774	if sh == nil {
775		return 0
776	}
777	out.SeekSet(int64(sh.Off))
778
779	// NT_FREEBSD_ABI_TAG
780	out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
781	out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
782	out.Write32(ELF_NOTE_FREEBSD_ABI_TAG)
783	out.WriteString(ELF_NOTE_FREEBSD_NAME)
784	out.Write32(ELF_NOTE_FREEBSD_VERSION)
785
786	// NT_FREEBSD_NOINIT_TAG
787	out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
788	out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
789	out.Write32(ELF_NOTE_FREEBSD_NOINIT_TAG)
790	out.WriteString(ELF_NOTE_FREEBSD_NAME)
791	out.Write32(0)
792
793	// NT_FREEBSD_FEATURE_CTL
794	out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
795	out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
796	out.Write32(ELF_NOTE_FREEBSD_FEATURE_CTL_TAG)
797	out.WriteString(ELF_NOTE_FREEBSD_NAME)
798	if *flagRace {
799		// The race detector can't handle ASLR, turn the ASLR off when compiling with -race.
800		out.Write32(ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE)
801	} else {
802		out.Write32(0)
803	}
804
805	return int(sh.Size)
806}
807
808func addbuildinfo(val string) {
809	if val == "gobuildid" {
810		buildID := *flagBuildid
811		if buildID == "" {
812			Exitf("-B gobuildid requires a Go build ID supplied via -buildid")
813		}
814
815		hashedBuildID := notsha256.Sum256([]byte(buildID))
816		buildinfo = hashedBuildID[:20]
817
818		return
819	}
820
821	if !strings.HasPrefix(val, "0x") {
822		Exitf("-B argument must start with 0x: %s", val)
823	}
824
825	ov := val
826	val = val[2:]
827
828	const maxLen = 32
829	if hex.DecodedLen(len(val)) > maxLen {
830		Exitf("-B option too long (max %d digits): %s", maxLen, ov)
831	}
832
833	b, err := hex.DecodeString(val)
834	if err != nil {
835		if err == hex.ErrLength {
836			Exitf("-B argument must have even number of digits: %s", ov)
837		}
838		if inv, ok := err.(hex.InvalidByteError); ok {
839			Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
840		}
841		Exitf("-B argument contains invalid hex: %s", ov)
842	}
843
844	buildinfo = b
845}
846
847// Build info note
848const (
849	ELF_NOTE_BUILDINFO_NAMESZ = 4
850	ELF_NOTE_BUILDINFO_TAG    = 3
851)
852
853var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
854
855func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
856	n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
857	return elfnote(sh, startva, resoff, n)
858}
859
860func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
861	n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
862	return elfnote(sh, startva, resoff, n)
863}
864
865func elfwritebuildinfo(out *OutBuf) int {
866	sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
867	if sh == nil {
868		return 0
869	}
870
871	out.Write(ELF_NOTE_BUILDINFO_NAME)
872	out.Write(buildinfo)
873	var zero = make([]byte, 4)
874	out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
875
876	return int(sh.Size)
877}
878
879func elfwritegobuildid(out *OutBuf) int {
880	sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
881	if sh == nil {
882		return 0
883	}
884
885	out.Write(ELF_NOTE_GO_NAME)
886	out.Write([]byte(*flagBuildid))
887	var zero = make([]byte, 4)
888	out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
889
890	return int(sh.Size)
891}
892
893// Go specific notes
894const (
895	ELF_NOTE_GOPKGLIST_TAG = 1
896	ELF_NOTE_GOABIHASH_TAG = 2
897	ELF_NOTE_GODEPS_TAG    = 3
898	ELF_NOTE_GOBUILDID_TAG = 4
899)
900
901var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
902
903var elfverneed int
904
905type Elfaux struct {
906	next *Elfaux
907	num  int
908	vers string
909}
910
911type Elflib struct {
912	next *Elflib
913	aux  *Elfaux
914	file string
915}
916
917func addelflib(list **Elflib, file string, vers string) *Elfaux {
918	var lib *Elflib
919
920	for lib = *list; lib != nil; lib = lib.next {
921		if lib.file == file {
922			goto havelib
923		}
924	}
925	lib = new(Elflib)
926	lib.next = *list
927	lib.file = file
928	*list = lib
929
930havelib:
931	for aux := lib.aux; aux != nil; aux = aux.next {
932		if aux.vers == vers {
933			return aux
934		}
935	}
936	aux := new(Elfaux)
937	aux.next = lib.aux
938	aux.vers = vers
939	lib.aux = aux
940
941	return aux
942}
943
944func elfdynhash(ctxt *Link) {
945	if !ctxt.IsELF {
946		return
947	}
948
949	nsym := Nelfsym
950	ldr := ctxt.loader
951	s := ldr.CreateSymForUpdate(".hash", 0)
952	s.SetType(sym.SELFROSECT)
953
954	i := nsym
955	nbucket := 1
956	for i > 0 {
957		nbucket++
958		i >>= 1
959	}
960
961	var needlib *Elflib
962	need := make([]*Elfaux, nsym)
963	chain := make([]uint32, nsym)
964	buckets := make([]uint32, nbucket)
965
966	for _, sy := range ldr.DynidSyms() {
967
968		dynid := ldr.SymDynid(sy)
969		if ldr.SymDynimpvers(sy) != "" {
970			need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy))
971		}
972
973		name := ldr.SymExtname(sy)
974		hc := elfhash(name)
975
976		b := hc % uint32(nbucket)
977		chain[dynid] = buckets[b]
978		buckets[b] = uint32(dynid)
979	}
980
981	// s390x (ELF64) hash table entries are 8 bytes
982	if ctxt.Arch.Family == sys.S390X {
983		s.AddUint64(ctxt.Arch, uint64(nbucket))
984		s.AddUint64(ctxt.Arch, uint64(nsym))
985		for i := 0; i < nbucket; i++ {
986			s.AddUint64(ctxt.Arch, uint64(buckets[i]))
987		}
988		for i := 0; i < nsym; i++ {
989			s.AddUint64(ctxt.Arch, uint64(chain[i]))
990		}
991	} else {
992		s.AddUint32(ctxt.Arch, uint32(nbucket))
993		s.AddUint32(ctxt.Arch, uint32(nsym))
994		for i := 0; i < nbucket; i++ {
995			s.AddUint32(ctxt.Arch, buckets[i])
996		}
997		for i := 0; i < nsym; i++ {
998			s.AddUint32(ctxt.Arch, chain[i])
999		}
1000	}
1001
1002	dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
1003
1004	// version symbols
1005	gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0)
1006	s = gnuVersionR
1007	i = 2
1008	nfile := 0
1009	for l := needlib; l != nil; l = l.next {
1010		nfile++
1011
1012		// header
1013		s.AddUint16(ctxt.Arch, 1) // table version
1014		j := 0
1015		for x := l.aux; x != nil; x = x.next {
1016			j++
1017		}
1018		s.AddUint16(ctxt.Arch, uint16(j))                        // aux count
1019		s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file))) // file string offset
1020		s.AddUint32(ctxt.Arch, 16)                               // offset from header to first aux
1021		if l.next != nil {
1022			s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
1023		} else {
1024			s.AddUint32(ctxt.Arch, 0)
1025		}
1026
1027		for x := l.aux; x != nil; x = x.next {
1028			x.num = i
1029			i++
1030
1031			// aux struct
1032			s.AddUint32(ctxt.Arch, elfhash(x.vers))                  // hash
1033			s.AddUint16(ctxt.Arch, 0)                                // flags
1034			s.AddUint16(ctxt.Arch, uint16(x.num))                    // other - index we refer to this by
1035			s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers))) // version string offset
1036			if x.next != nil {
1037				s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
1038			} else {
1039				s.AddUint32(ctxt.Arch, 0)
1040			}
1041		}
1042	}
1043
1044	// version references
1045	gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0)
1046	s = gnuVersion
1047
1048	for i := 0; i < nsym; i++ {
1049		if i == 0 {
1050			s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
1051		} else if need[i] == nil {
1052			s.AddUint16(ctxt.Arch, 1) // global
1053		} else {
1054			s.AddUint16(ctxt.Arch, uint16(need[i].num))
1055		}
1056	}
1057
1058	s = ldr.CreateSymForUpdate(".dynamic", 0)
1059
1060	var dtFlags1 elf.DynFlag1
1061	if *flagBindNow {
1062		dtFlags1 |= elf.DF_1_NOW
1063		Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS, uint64(elf.DF_BIND_NOW))
1064	}
1065	if ctxt.BuildMode == BuildModePIE {
1066		dtFlags1 |= elf.DF_1_PIE
1067	}
1068	Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(dtFlags1))
1069
1070	elfverneed = nfile
1071	if elfverneed != 0 {
1072		elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym())
1073		Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile))
1074		elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym())
1075	}
1076
1077	sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0)
1078	if sy.Size() > 0 {
1079		if elfRelType == ".rela" {
1080			Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA))
1081		} else {
1082			Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL))
1083		}
1084		elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym())
1085		elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym())
1086	}
1087
1088	Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0)
1089}
1090
1091func elfphload(seg *sym.Segment) *ElfPhdr {
1092	ph := newElfPhdr()
1093	ph.Type = elf.PT_LOAD
1094	if seg.Rwx&4 != 0 {
1095		ph.Flags |= elf.PF_R
1096	}
1097	if seg.Rwx&2 != 0 {
1098		ph.Flags |= elf.PF_W
1099	}
1100	if seg.Rwx&1 != 0 {
1101		ph.Flags |= elf.PF_X
1102	}
1103	ph.Vaddr = seg.Vaddr
1104	ph.Paddr = seg.Vaddr
1105	ph.Memsz = seg.Length
1106	ph.Off = seg.Fileoff
1107	ph.Filesz = seg.Filelen
1108	ph.Align = uint64(*FlagRound)
1109
1110	return ph
1111}
1112
1113func elfphrelro(seg *sym.Segment) {
1114	ph := newElfPhdr()
1115	ph.Type = elf.PT_GNU_RELRO
1116	ph.Flags = elf.PF_R
1117	ph.Vaddr = seg.Vaddr
1118	ph.Paddr = seg.Vaddr
1119	ph.Memsz = seg.Length
1120	ph.Off = seg.Fileoff
1121	ph.Filesz = seg.Filelen
1122	ph.Align = uint64(*FlagRound)
1123}
1124
1125func elfshname(name string) *ElfShdr {
1126	for i := 0; i < nelfstr; i++ {
1127		if name != elfstr[i].s {
1128			continue
1129		}
1130		off := elfstr[i].off
1131		for i = 0; i < int(ehdr.Shnum); i++ {
1132			sh := shdr[i]
1133			if sh.Name == uint32(off) {
1134				return sh
1135			}
1136		}
1137		return newElfShdr(int64(off))
1138	}
1139	Exitf("cannot find elf name %s", name)
1140	return nil
1141}
1142
1143// Create an ElfShdr for the section with name.
1144// Create a duplicate if one already exists with that name.
1145func elfshnamedup(name string) *ElfShdr {
1146	for i := 0; i < nelfstr; i++ {
1147		if name == elfstr[i].s {
1148			off := elfstr[i].off
1149			return newElfShdr(int64(off))
1150		}
1151	}
1152
1153	Errorf(nil, "cannot find elf name %s", name)
1154	errorexit()
1155	return nil
1156}
1157
1158func elfshalloc(sect *sym.Section) *ElfShdr {
1159	sh := elfshname(sect.Name)
1160	sect.Elfsect = sh
1161	return sh
1162}
1163
1164func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
1165	var sh *ElfShdr
1166
1167	if sect.Name == ".text" {
1168		if sect.Elfsect == nil {
1169			sect.Elfsect = elfshnamedup(sect.Name)
1170		}
1171		sh = sect.Elfsect.(*ElfShdr)
1172	} else {
1173		sh = elfshalloc(sect)
1174	}
1175
1176	// If this section has already been set up as a note, we assume type_ and
1177	// flags are already correct, but the other fields still need filling in.
1178	if sh.Type == uint32(elf.SHT_NOTE) {
1179		if linkmode != LinkExternal {
1180			// TODO(mwhudson): the approach here will work OK when
1181			// linking internally for notes that we want to be included
1182			// in a loadable segment (e.g. the abihash note) but not for
1183			// notes that we do not want to be mapped (e.g. the package
1184			// list note). The real fix is probably to define new values
1185			// for Symbol.Type corresponding to mapped and unmapped notes
1186			// and handle them in dodata().
1187			Errorf(nil, "sh.Type == SHT_NOTE in elfshbits when linking internally")
1188		}
1189		sh.Addralign = uint64(sect.Align)
1190		sh.Size = sect.Length
1191		sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
1192		return sh
1193	}
1194	if sh.Type > 0 {
1195		return sh
1196	}
1197
1198	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
1199		switch sect.Name {
1200		case ".init_array":
1201			sh.Type = uint32(elf.SHT_INIT_ARRAY)
1202		default:
1203			sh.Type = uint32(elf.SHT_PROGBITS)
1204		}
1205	} else {
1206		sh.Type = uint32(elf.SHT_NOBITS)
1207	}
1208	sh.Flags = uint64(elf.SHF_ALLOC)
1209	if sect.Rwx&1 != 0 {
1210		sh.Flags |= uint64(elf.SHF_EXECINSTR)
1211	}
1212	if sect.Rwx&2 != 0 {
1213		sh.Flags |= uint64(elf.SHF_WRITE)
1214	}
1215	if sect.Name == ".tbss" {
1216		sh.Flags |= uint64(elf.SHF_TLS)
1217		sh.Type = uint32(elf.SHT_NOBITS)
1218	}
1219	if linkmode != LinkExternal {
1220		sh.Addr = sect.Vaddr
1221	}
1222
1223	if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
1224		sh.Flags = 0
1225		sh.Addr = 0
1226		if sect.Compressed {
1227			sh.Flags |= uint64(elf.SHF_COMPRESSED)
1228		}
1229	}
1230
1231	sh.Addralign = uint64(sect.Align)
1232	sh.Size = sect.Length
1233	if sect.Name != ".tbss" {
1234		sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
1235	}
1236
1237	return sh
1238}
1239
1240func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
1241	// If main section is SHT_NOBITS, nothing to relocate.
1242	// Also nothing to relocate in .shstrtab or notes.
1243	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1244		return nil
1245	}
1246	if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
1247		return nil
1248	}
1249	if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) {
1250		return nil
1251	}
1252
1253	typ := elf.SHT_REL
1254	if elfRelType == ".rela" {
1255		typ = elf.SHT_RELA
1256	}
1257
1258	sh := elfshname(elfRelType + sect.Name)
1259	// There could be multiple text sections but each needs
1260	// its own .rela.text.
1261
1262	if sect.Name == ".text" {
1263		if sh.Info != 0 && sh.Info != uint32(sect.Elfsect.(*ElfShdr).shnum) {
1264			sh = elfshnamedup(elfRelType + sect.Name)
1265		}
1266	}
1267
1268	sh.Type = uint32(typ)
1269	sh.Entsize = uint64(arch.RegSize) * 2
1270	if typ == elf.SHT_RELA {
1271		sh.Entsize += uint64(arch.RegSize)
1272	}
1273	sh.Link = uint32(elfshname(".symtab").shnum)
1274	sh.Info = uint32(sect.Elfsect.(*ElfShdr).shnum)
1275	sh.Off = sect.Reloff
1276	sh.Size = sect.Rellen
1277	sh.Addralign = uint64(arch.RegSize)
1278	return sh
1279}
1280
1281func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
1282	// If main section is SHT_NOBITS, nothing to relocate.
1283	// Also nothing to relocate in .shstrtab.
1284	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1285		return
1286	}
1287	if sect.Name == ".shstrtab" {
1288		return
1289	}
1290
1291	ldr := ctxt.loader
1292	for i, s := range syms {
1293		if !ldr.AttrReachable(s) {
1294			panic("should never happen")
1295		}
1296		if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1297			syms = syms[i:]
1298			break
1299		}
1300	}
1301
1302	eaddr := sect.Vaddr + sect.Length
1303	for _, s := range syms {
1304		if !ldr.AttrReachable(s) {
1305			continue
1306		}
1307		if ldr.SymValue(s) >= int64(eaddr) {
1308			break
1309		}
1310
1311		// Compute external relocations on the go, and pass to
1312		// ELF.Reloc1 to stream out.
1313		relocs := ldr.Relocs(s)
1314		for ri := 0; ri < relocs.Count(); ri++ {
1315			r := relocs.At(ri)
1316			rr, ok := extreloc(ctxt, ldr, s, r)
1317			if !ok {
1318				continue
1319			}
1320			if rr.Xsym == 0 {
1321				ldr.Errorf(s, "missing xsym in relocation")
1322				continue
1323			}
1324			esr := ElfSymForReloc(ctxt, rr.Xsym)
1325			if esr == 0 {
1326				ldr.Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()), ldr.SymType(r.Sym()).String())
1327			}
1328			if !ldr.AttrReachable(rr.Xsym) {
1329				ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
1330			}
1331			if !thearch.ELF.Reloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
1332				ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym()))
1333			}
1334		}
1335	}
1336
1337	// sanity check
1338	if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
1339		panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen))
1340	}
1341}
1342
1343func elfEmitReloc(ctxt *Link) {
1344	for ctxt.Out.Offset()&7 != 0 {
1345		ctxt.Out.Write8(0)
1346	}
1347
1348	sizeExtRelocs(ctxt, thearch.ELF.RelocSize)
1349	relocSect, wg := relocSectFn(ctxt, elfrelocsect)
1350
1351	for _, sect := range Segtext.Sections {
1352		if sect.Name == ".text" {
1353			relocSect(ctxt, sect, ctxt.Textp)
1354		} else {
1355			relocSect(ctxt, sect, ctxt.datap)
1356		}
1357	}
1358
1359	for _, sect := range Segrodata.Sections {
1360		relocSect(ctxt, sect, ctxt.datap)
1361	}
1362	for _, sect := range Segrelrodata.Sections {
1363		relocSect(ctxt, sect, ctxt.datap)
1364	}
1365	for _, sect := range Segdata.Sections {
1366		relocSect(ctxt, sect, ctxt.datap)
1367	}
1368	for i := 0; i < len(Segdwarf.Sections); i++ {
1369		sect := Segdwarf.Sections[i]
1370		si := dwarfp[i]
1371		if si.secSym() != loader.Sym(sect.Sym) ||
1372			ctxt.loader.SymSect(si.secSym()) != sect {
1373			panic("inconsistency between dwarfp and Segdwarf")
1374		}
1375		relocSect(ctxt, sect, si.syms)
1376	}
1377	wg.Wait()
1378}
1379
1380func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
1381	ldr := ctxt.loader
1382	s := ldr.CreateSymForUpdate(sectionName, 0)
1383	s.SetType(sym.SELFROSECT)
1384	// namesz
1385	s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
1386	// descsz
1387	s.AddUint32(ctxt.Arch, uint32(len(desc)))
1388	// tag
1389	s.AddUint32(ctxt.Arch, tag)
1390	// name + padding
1391	s.AddBytes(ELF_NOTE_GO_NAME)
1392	for len(s.Data())%4 != 0 {
1393		s.AddUint8(0)
1394	}
1395	// desc + padding
1396	s.AddBytes(desc)
1397	for len(s.Data())%4 != 0 {
1398		s.AddUint8(0)
1399	}
1400	s.SetSize(int64(len(s.Data())))
1401	s.SetAlign(4)
1402}
1403
1404func (ctxt *Link) doelf() {
1405	ldr := ctxt.loader
1406
1407	/* predefine strings we need for section headers */
1408
1409	addshstr := func(s string) int {
1410		off := len(elfshstrdat)
1411		elfshstrdat = append(elfshstrdat, s...)
1412		elfshstrdat = append(elfshstrdat, 0)
1413		return off
1414	}
1415
1416	shstrtabAddstring := func(s string) {
1417		off := addshstr(s)
1418		elfsetstring(ctxt, 0, s, int(off))
1419	}
1420
1421	shstrtabAddstring("")
1422	shstrtabAddstring(".text")
1423	shstrtabAddstring(".noptrdata")
1424	shstrtabAddstring(".data")
1425	shstrtabAddstring(".bss")
1426	shstrtabAddstring(".noptrbss")
1427	shstrtabAddstring(".go.fuzzcntrs")
1428	shstrtabAddstring(".go.buildinfo")
1429	if ctxt.IsMIPS() {
1430		shstrtabAddstring(".MIPS.abiflags")
1431		shstrtabAddstring(".gnu.attributes")
1432	}
1433
1434	// generate .tbss section for dynamic internal linker or external
1435	// linking, so that various binutils could correctly calculate
1436	// PT_TLS size. See https://golang.org/issue/5200.
1437	if !*FlagD || ctxt.IsExternal() {
1438		shstrtabAddstring(".tbss")
1439	}
1440	if ctxt.IsNetbsd() {
1441		shstrtabAddstring(".note.netbsd.ident")
1442		if *flagRace {
1443			shstrtabAddstring(".note.netbsd.pax")
1444		}
1445	}
1446	if ctxt.IsOpenbsd() {
1447		shstrtabAddstring(".note.openbsd.ident")
1448	}
1449	if ctxt.IsFreebsd() {
1450		shstrtabAddstring(".note.tag")
1451	}
1452	if len(buildinfo) > 0 {
1453		shstrtabAddstring(".note.gnu.build-id")
1454	}
1455	if *flagBuildid != "" {
1456		shstrtabAddstring(".note.go.buildid")
1457	}
1458	shstrtabAddstring(".elfdata")
1459	shstrtabAddstring(".rodata")
1460	// See the comment about data.rel.ro.FOO section names in data.go.
1461	relro_prefix := ""
1462	if ctxt.UseRelro() {
1463		shstrtabAddstring(".data.rel.ro")
1464		relro_prefix = ".data.rel.ro"
1465	}
1466	shstrtabAddstring(relro_prefix + ".typelink")
1467	shstrtabAddstring(relro_prefix + ".itablink")
1468	shstrtabAddstring(relro_prefix + ".gosymtab")
1469	shstrtabAddstring(relro_prefix + ".gopclntab")
1470
1471	if ctxt.IsExternal() {
1472		*FlagD = true
1473
1474		shstrtabAddstring(elfRelType + ".text")
1475		shstrtabAddstring(elfRelType + ".rodata")
1476		shstrtabAddstring(elfRelType + relro_prefix + ".typelink")
1477		shstrtabAddstring(elfRelType + relro_prefix + ".itablink")
1478		shstrtabAddstring(elfRelType + relro_prefix + ".gosymtab")
1479		shstrtabAddstring(elfRelType + relro_prefix + ".gopclntab")
1480		shstrtabAddstring(elfRelType + ".noptrdata")
1481		shstrtabAddstring(elfRelType + ".data")
1482		if ctxt.UseRelro() {
1483			shstrtabAddstring(elfRelType + ".data.rel.ro")
1484		}
1485		shstrtabAddstring(elfRelType + ".go.buildinfo")
1486		if ctxt.IsMIPS() {
1487			shstrtabAddstring(elfRelType + ".MIPS.abiflags")
1488			shstrtabAddstring(elfRelType + ".gnu.attributes")
1489		}
1490
1491		// add a .note.GNU-stack section to mark the stack as non-executable
1492		shstrtabAddstring(".note.GNU-stack")
1493
1494		if ctxt.IsShared() {
1495			shstrtabAddstring(".note.go.abihash")
1496			shstrtabAddstring(".note.go.pkg-list")
1497			shstrtabAddstring(".note.go.deps")
1498		}
1499	}
1500
1501	hasinitarr := ctxt.linkShared
1502
1503	/* shared library initializer */
1504	switch ctxt.BuildMode {
1505	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
1506		hasinitarr = true
1507	}
1508
1509	if hasinitarr {
1510		shstrtabAddstring(".init_array")
1511		shstrtabAddstring(elfRelType + ".init_array")
1512	}
1513
1514	if !*FlagS {
1515		shstrtabAddstring(".symtab")
1516		shstrtabAddstring(".strtab")
1517	}
1518	if !*FlagW {
1519		dwarfaddshstrings(ctxt, shstrtabAddstring)
1520	}
1521
1522	shstrtabAddstring(".shstrtab")
1523
1524	if !*FlagD { /* -d suppresses dynamic loader format */
1525		shstrtabAddstring(".interp")
1526		shstrtabAddstring(".hash")
1527		shstrtabAddstring(".got")
1528		if ctxt.IsPPC64() {
1529			shstrtabAddstring(".glink")
1530		}
1531		shstrtabAddstring(".got.plt")
1532		shstrtabAddstring(".dynamic")
1533		shstrtabAddstring(".dynsym")
1534		shstrtabAddstring(".dynstr")
1535		shstrtabAddstring(elfRelType)
1536		shstrtabAddstring(elfRelType + ".plt")
1537
1538		shstrtabAddstring(".plt")
1539		shstrtabAddstring(".gnu.version")
1540		shstrtabAddstring(".gnu.version_r")
1541
1542		/* dynamic symbol table - first entry all zeros */
1543		dynsym := ldr.CreateSymForUpdate(".dynsym", 0)
1544
1545		dynsym.SetType(sym.SELFROSECT)
1546		if elf64 {
1547			dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE)
1548		} else {
1549			dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE)
1550		}
1551
1552		/* dynamic string table */
1553		dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
1554
1555		dynstr.SetType(sym.SELFROSECT)
1556		if dynstr.Size() == 0 {
1557			dynstr.Addstring("")
1558		}
1559
1560		/* relocation table */
1561		s := ldr.CreateSymForUpdate(elfRelType, 0)
1562		s.SetType(sym.SELFROSECT)
1563
1564		/* global offset table */
1565		got := ldr.CreateSymForUpdate(".got", 0)
1566		if ctxt.UseRelro() {
1567			got.SetType(sym.SELFRELROSECT)
1568		} else {
1569			got.SetType(sym.SELFGOT) // writable
1570		}
1571
1572		/* ppc64 glink resolver */
1573		if ctxt.IsPPC64() {
1574			s := ldr.CreateSymForUpdate(".glink", 0)
1575			s.SetType(sym.SELFRXSECT)
1576		}
1577
1578		/* hash */
1579		hash := ldr.CreateSymForUpdate(".hash", 0)
1580		hash.SetType(sym.SELFROSECT)
1581
1582		gotplt := ldr.CreateSymForUpdate(".got.plt", 0)
1583		if ctxt.UseRelro() && *flagBindNow {
1584			gotplt.SetType(sym.SELFRELROSECT)
1585		} else {
1586			gotplt.SetType(sym.SELFSECT) // writable
1587		}
1588
1589		plt := ldr.CreateSymForUpdate(".plt", 0)
1590		if ctxt.IsPPC64() {
1591			// In the ppc64 ABI, .plt is a data section
1592			// written by the dynamic linker.
1593			plt.SetType(sym.SELFSECT)
1594		} else {
1595			plt.SetType(sym.SELFRXSECT)
1596		}
1597
1598		s = ldr.CreateSymForUpdate(elfRelType+".plt", 0)
1599		s.SetType(sym.SELFROSECT)
1600
1601		s = ldr.CreateSymForUpdate(".gnu.version", 0)
1602		s.SetType(sym.SELFROSECT)
1603
1604		s = ldr.CreateSymForUpdate(".gnu.version_r", 0)
1605		s.SetType(sym.SELFROSECT)
1606
1607		/* define dynamic elf table */
1608		dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
1609		switch {
1610		case thearch.ELF.DynamicReadOnly:
1611			dynamic.SetType(sym.SELFROSECT)
1612		case ctxt.UseRelro():
1613			dynamic.SetType(sym.SELFRELROSECT)
1614		default:
1615			dynamic.SetType(sym.SELFSECT)
1616		}
1617
1618		if ctxt.IsS390X() {
1619			// S390X uses .got instead of .got.plt
1620			gotplt = got
1621		}
1622		thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym())
1623
1624		/*
1625		 * .dynamic table
1626		 */
1627		elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym())
1628
1629		elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym())
1630		if elf64 {
1631			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE)
1632		} else {
1633			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE)
1634		}
1635		elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym())
1636		elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym())
1637		if elfRelType == ".rela" {
1638			rela := ldr.LookupOrCreateSym(".rela", 0)
1639			elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela)
1640			elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela)
1641			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE)
1642		} else {
1643			rel := ldr.LookupOrCreateSym(".rel", 0)
1644			elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel)
1645			elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel)
1646			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE)
1647		}
1648
1649		if rpath.val != "" {
1650			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
1651		}
1652
1653		if ctxt.IsPPC64() {
1654			elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym())
1655		} else {
1656			elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym())
1657		}
1658
1659		if ctxt.IsPPC64() {
1660			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0)
1661		}
1662
1663		// Solaris dynamic linker can't handle an empty .rela.plt if
1664		// DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL,
1665		// DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the
1666		// size of .rel(a).plt section.
1667
1668		Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0)
1669	}
1670
1671	if ctxt.IsShared() {
1672		// The go.link.abihashbytes symbol will be pointed at the appropriate
1673		// part of the .note.go.abihash section in data.go:func address().
1674		s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
1675		sb := ldr.MakeSymbolUpdater(s)
1676		ldr.SetAttrLocal(s, true)
1677		sb.SetType(sym.SRODATA)
1678		ldr.SetAttrSpecial(s, true)
1679		sb.SetReachable(true)
1680		sb.SetSize(notsha256.Size)
1681
1682		sort.Sort(byPkg(ctxt.Library))
1683		h := notsha256.New()
1684		for _, l := range ctxt.Library {
1685			h.Write(l.Fingerprint[:])
1686		}
1687		addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
1688		addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
1689		var deplist []string
1690		for _, shlib := range ctxt.Shlibs {
1691			deplist = append(deplist, filepath.Base(shlib.Path))
1692		}
1693		addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
1694	}
1695
1696	if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
1697		addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
1698	}
1699
1700	//type mipsGnuAttributes struct {
1701	//	version uint8   // 'A'
1702	//	length  uint32  // 15 including itself
1703	//	gnu     [4]byte // "gnu\0"
1704	//	tag     uint8   // 1:file, 2: section, 3: symbol, 1 here
1705	//	taglen  uint32  // tag length, including tag, 7 here
1706	//	tagfp   uint8   // 4
1707	//	fpAbi  uint8    // see .MIPS.abiflags
1708	//}
1709	if ctxt.IsMIPS() {
1710		gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0)
1711		gnuattributes.SetType(sym.SELFROSECT)
1712		gnuattributes.SetReachable(true)
1713		gnuattributes.AddUint8('A')               // version 'A'
1714		gnuattributes.AddUint32(ctxt.Arch, 15)    // length 15 including itself
1715		gnuattributes.AddBytes([]byte("gnu\x00")) // "gnu\0"
1716		gnuattributes.AddUint8(1)                 // 1:file, 2: section, 3: symbol, 1 here
1717		gnuattributes.AddUint32(ctxt.Arch, 7)     // tag length, including tag, 7 here
1718		gnuattributes.AddUint8(4)                 // 4 for FP, 8 for MSA
1719		if buildcfg.GOMIPS == "softfloat" {
1720			gnuattributes.AddUint8(MIPS_FPABI_SOFT)
1721		} else {
1722			// Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
1723			//       It is not for 'ANY'.
1724			// TODO: switch to FPXX after be sure that no odd-number-fpr is used.
1725			gnuattributes.AddUint8(MIPS_FPABI_ANY)
1726		}
1727	}
1728}
1729
1730// Do not write DT_NULL.  elfdynhash will finish it.
1731func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) {
1732	if s == 0 {
1733		panic("bad symbol in shsym2")
1734	}
1735	addr := ldr.SymValue(s)
1736	if sh.Flags&uint64(elf.SHF_ALLOC) != 0 {
1737		sh.Addr = uint64(addr)
1738	}
1739	sh.Off = uint64(datoff(ldr, s, addr))
1740	sh.Size = uint64(ldr.SymSize(s))
1741}
1742
1743func phsh(ph *ElfPhdr, sh *ElfShdr) {
1744	ph.Vaddr = sh.Addr
1745	ph.Paddr = ph.Vaddr
1746	ph.Off = sh.Off
1747	ph.Filesz = sh.Size
1748	ph.Memsz = sh.Size
1749	ph.Align = sh.Addralign
1750}
1751
1752func Asmbelfsetup() {
1753	/* This null SHdr must appear before all others */
1754	elfshname("")
1755
1756	for _, sect := range Segtext.Sections {
1757		// There could be multiple .text sections. Instead check the Elfsect
1758		// field to determine if already has an ElfShdr and if not, create one.
1759		if sect.Name == ".text" {
1760			if sect.Elfsect == nil {
1761				sect.Elfsect = elfshnamedup(sect.Name)
1762			}
1763		} else {
1764			elfshalloc(sect)
1765		}
1766	}
1767	for _, sect := range Segrodata.Sections {
1768		elfshalloc(sect)
1769	}
1770	for _, sect := range Segrelrodata.Sections {
1771		elfshalloc(sect)
1772	}
1773	for _, sect := range Segdata.Sections {
1774		elfshalloc(sect)
1775	}
1776	for _, sect := range Segdwarf.Sections {
1777		elfshalloc(sect)
1778	}
1779}
1780
1781func asmbElf(ctxt *Link) {
1782	var symo int64
1783	symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
1784	symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
1785	ctxt.Out.SeekSet(symo)
1786	if *FlagS {
1787		ctxt.Out.Write(elfshstrdat)
1788	} else {
1789		ctxt.Out.SeekSet(symo)
1790		asmElfSym(ctxt)
1791		ctxt.Out.Write(elfstrdat)
1792		ctxt.Out.Write(elfshstrdat)
1793		if ctxt.IsExternal() {
1794			elfEmitReloc(ctxt)
1795		}
1796	}
1797	ctxt.Out.SeekSet(0)
1798
1799	ldr := ctxt.loader
1800	eh := getElfEhdr()
1801	switch ctxt.Arch.Family {
1802	default:
1803		Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
1804	case sys.MIPS, sys.MIPS64:
1805		eh.Machine = uint16(elf.EM_MIPS)
1806	case sys.Loong64:
1807		eh.Machine = uint16(elf.EM_LOONGARCH)
1808	case sys.ARM:
1809		eh.Machine = uint16(elf.EM_ARM)
1810	case sys.AMD64:
1811		eh.Machine = uint16(elf.EM_X86_64)
1812	case sys.ARM64:
1813		eh.Machine = uint16(elf.EM_AARCH64)
1814	case sys.I386:
1815		eh.Machine = uint16(elf.EM_386)
1816	case sys.PPC64:
1817		eh.Machine = uint16(elf.EM_PPC64)
1818	case sys.RISCV64:
1819		eh.Machine = uint16(elf.EM_RISCV)
1820	case sys.S390X:
1821		eh.Machine = uint16(elf.EM_S390)
1822	}
1823
1824	elfreserve := int64(ELFRESERVE)
1825
1826	numtext := int64(0)
1827	for _, sect := range Segtext.Sections {
1828		if sect.Name == ".text" {
1829			numtext++
1830		}
1831	}
1832
1833	// If there are multiple text sections, extra space is needed
1834	// in the elfreserve for the additional .text and .rela.text
1835	// section headers.  It can handle 4 extra now. Headers are
1836	// 64 bytes.
1837
1838	if numtext > 4 {
1839		elfreserve += elfreserve + numtext*64*2
1840	}
1841
1842	startva := *FlagTextAddr - int64(HEADR)
1843	resoff := elfreserve
1844
1845	var pph *ElfPhdr
1846	var pnote *ElfPhdr
1847	getpnote := func() *ElfPhdr {
1848		if pnote == nil {
1849			pnote = newElfPhdr()
1850			pnote.Type = elf.PT_NOTE
1851			pnote.Flags = elf.PF_R
1852		}
1853		return pnote
1854	}
1855	if *flagRace && ctxt.IsNetbsd() {
1856		sh := elfshname(".note.netbsd.pax")
1857		resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
1858		phsh(getpnote(), sh)
1859	}
1860	if ctxt.LinkMode == LinkExternal {
1861		/* skip program headers */
1862		eh.Phoff = 0
1863
1864		eh.Phentsize = 0
1865
1866		if ctxt.BuildMode == BuildModeShared {
1867			sh := elfshname(".note.go.pkg-list")
1868			sh.Type = uint32(elf.SHT_NOTE)
1869			sh = elfshname(".note.go.abihash")
1870			sh.Type = uint32(elf.SHT_NOTE)
1871			sh.Flags = uint64(elf.SHF_ALLOC)
1872			sh = elfshname(".note.go.deps")
1873			sh.Type = uint32(elf.SHT_NOTE)
1874		}
1875
1876		if *flagBuildid != "" {
1877			sh := elfshname(".note.go.buildid")
1878			sh.Type = uint32(elf.SHT_NOTE)
1879			sh.Flags = uint64(elf.SHF_ALLOC)
1880		}
1881
1882		goto elfobj
1883	}
1884
1885	/* program header info */
1886	pph = newElfPhdr()
1887
1888	pph.Type = elf.PT_PHDR
1889	pph.Flags = elf.PF_R
1890	pph.Off = uint64(eh.Ehsize)
1891	pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
1892	pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
1893	pph.Align = uint64(*FlagRound)
1894
1895	/*
1896	 * PHDR must be in a loaded segment. Adjust the text
1897	 * segment boundaries downwards to include it.
1898	 */
1899	{
1900		o := int64(Segtext.Vaddr - pph.Vaddr)
1901		Segtext.Vaddr -= uint64(o)
1902		Segtext.Length += uint64(o)
1903		o = int64(Segtext.Fileoff - pph.Off)
1904		Segtext.Fileoff -= uint64(o)
1905		Segtext.Filelen += uint64(o)
1906	}
1907
1908	if !*FlagD { /* -d suppresses dynamic loader format */
1909		/* interpreter */
1910		sh := elfshname(".interp")
1911
1912		sh.Type = uint32(elf.SHT_PROGBITS)
1913		sh.Flags = uint64(elf.SHF_ALLOC)
1914		sh.Addralign = 1
1915
1916		if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" {
1917			interpreter = buildcfg.GO_LDSO
1918		}
1919
1920		if interpreter == "" {
1921			switch ctxt.HeadType {
1922			case objabi.Hlinux:
1923				if buildcfg.GOOS == "android" {
1924					interpreter = thearch.ELF.Androiddynld
1925					if interpreter == "" {
1926						Exitf("ELF interpreter not set")
1927					}
1928				} else {
1929					interpreter = thearch.ELF.Linuxdynld
1930					// If interpreter does not exist, try musl instead.
1931					// This lets the same cmd/link binary work on
1932					// both glibc-based and musl-based systems.
1933					if _, err := os.Stat(interpreter); err != nil {
1934						if musl := thearch.ELF.LinuxdynldMusl; musl != "" {
1935							if _, err := os.Stat(musl); err == nil {
1936								interpreter = musl
1937							}
1938						}
1939					}
1940				}
1941
1942			case objabi.Hfreebsd:
1943				interpreter = thearch.ELF.Freebsddynld
1944
1945			case objabi.Hnetbsd:
1946				interpreter = thearch.ELF.Netbsddynld
1947
1948			case objabi.Hopenbsd:
1949				interpreter = thearch.ELF.Openbsddynld
1950
1951			case objabi.Hdragonfly:
1952				interpreter = thearch.ELF.Dragonflydynld
1953
1954			case objabi.Hsolaris:
1955				interpreter = thearch.ELF.Solarisdynld
1956			}
1957		}
1958
1959		resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
1960
1961		ph := newElfPhdr()
1962		ph.Type = elf.PT_INTERP
1963		ph.Flags = elf.PF_R
1964		phsh(ph, sh)
1965	}
1966
1967	if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd {
1968		var sh *ElfShdr
1969		switch ctxt.HeadType {
1970		case objabi.Hnetbsd:
1971			sh = elfshname(".note.netbsd.ident")
1972			resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
1973
1974		case objabi.Hopenbsd:
1975			sh = elfshname(".note.openbsd.ident")
1976			resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
1977
1978		case objabi.Hfreebsd:
1979			sh = elfshname(".note.tag")
1980			resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff)))
1981		}
1982		// NetBSD, OpenBSD and FreeBSD require ident in an independent segment.
1983		pnotei := newElfPhdr()
1984		pnotei.Type = elf.PT_NOTE
1985		pnotei.Flags = elf.PF_R
1986		phsh(pnotei, sh)
1987	}
1988
1989	if len(buildinfo) > 0 {
1990		sh := elfshname(".note.gnu.build-id")
1991		resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
1992		phsh(getpnote(), sh)
1993	}
1994
1995	if *flagBuildid != "" {
1996		sh := elfshname(".note.go.buildid")
1997		resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
1998		phsh(getpnote(), sh)
1999	}
2000
2001	// Additions to the reserved area must be above this line.
2002
2003	elfphload(&Segtext)
2004	if len(Segrodata.Sections) > 0 {
2005		elfphload(&Segrodata)
2006	}
2007	if len(Segrelrodata.Sections) > 0 {
2008		elfphload(&Segrelrodata)
2009		elfphrelro(&Segrelrodata)
2010	}
2011	elfphload(&Segdata)
2012
2013	/* Dynamic linking sections */
2014	if !*FlagD {
2015		sh := elfshname(".dynsym")
2016		sh.Type = uint32(elf.SHT_DYNSYM)
2017		sh.Flags = uint64(elf.SHF_ALLOC)
2018		if elf64 {
2019			sh.Entsize = ELF64SYMSIZE
2020		} else {
2021			sh.Entsize = ELF32SYMSIZE
2022		}
2023		sh.Addralign = uint64(ctxt.Arch.RegSize)
2024		sh.Link = uint32(elfshname(".dynstr").shnum)
2025
2026		// sh.info is the index of first non-local symbol (number of local symbols)
2027		s := ldr.Lookup(".dynsym", 0)
2028		i := uint32(0)
2029		for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2030			i++
2031			if !ldr.AttrLocal(sub) {
2032				break
2033			}
2034		}
2035		sh.Info = i
2036		shsym(sh, ldr, s)
2037
2038		sh = elfshname(".dynstr")
2039		sh.Type = uint32(elf.SHT_STRTAB)
2040		sh.Flags = uint64(elf.SHF_ALLOC)
2041		sh.Addralign = 1
2042		shsym(sh, ldr, ldr.Lookup(".dynstr", 0))
2043
2044		if elfverneed != 0 {
2045			sh := elfshname(".gnu.version")
2046			sh.Type = uint32(elf.SHT_GNU_VERSYM)
2047			sh.Flags = uint64(elf.SHF_ALLOC)
2048			sh.Addralign = 2
2049			sh.Link = uint32(elfshname(".dynsym").shnum)
2050			sh.Entsize = 2
2051			shsym(sh, ldr, ldr.Lookup(".gnu.version", 0))
2052
2053			sh = elfshname(".gnu.version_r")
2054			sh.Type = uint32(elf.SHT_GNU_VERNEED)
2055			sh.Flags = uint64(elf.SHF_ALLOC)
2056			sh.Addralign = uint64(ctxt.Arch.RegSize)
2057			sh.Info = uint32(elfverneed)
2058			sh.Link = uint32(elfshname(".dynstr").shnum)
2059			shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0))
2060		}
2061
2062		if elfRelType == ".rela" {
2063			sh := elfshname(".rela.plt")
2064			sh.Type = uint32(elf.SHT_RELA)
2065			sh.Flags = uint64(elf.SHF_ALLOC)
2066			sh.Entsize = ELF64RELASIZE
2067			sh.Addralign = uint64(ctxt.Arch.RegSize)
2068			sh.Link = uint32(elfshname(".dynsym").shnum)
2069			sh.Info = uint32(elfshname(".plt").shnum)
2070			shsym(sh, ldr, ldr.Lookup(".rela.plt", 0))
2071
2072			sh = elfshname(".rela")
2073			sh.Type = uint32(elf.SHT_RELA)
2074			sh.Flags = uint64(elf.SHF_ALLOC)
2075			sh.Entsize = ELF64RELASIZE
2076			sh.Addralign = 8
2077			sh.Link = uint32(elfshname(".dynsym").shnum)
2078			shsym(sh, ldr, ldr.Lookup(".rela", 0))
2079		} else {
2080			sh := elfshname(".rel.plt")
2081			sh.Type = uint32(elf.SHT_REL)
2082			sh.Flags = uint64(elf.SHF_ALLOC)
2083			sh.Entsize = ELF32RELSIZE
2084			sh.Addralign = 4
2085			sh.Link = uint32(elfshname(".dynsym").shnum)
2086			shsym(sh, ldr, ldr.Lookup(".rel.plt", 0))
2087
2088			sh = elfshname(".rel")
2089			sh.Type = uint32(elf.SHT_REL)
2090			sh.Flags = uint64(elf.SHF_ALLOC)
2091			sh.Entsize = ELF32RELSIZE
2092			sh.Addralign = 4
2093			sh.Link = uint32(elfshname(".dynsym").shnum)
2094			shsym(sh, ldr, ldr.Lookup(".rel", 0))
2095		}
2096
2097		if elf.Machine(eh.Machine) == elf.EM_PPC64 {
2098			sh := elfshname(".glink")
2099			sh.Type = uint32(elf.SHT_PROGBITS)
2100			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
2101			sh.Addralign = 4
2102			shsym(sh, ldr, ldr.Lookup(".glink", 0))
2103		}
2104
2105		sh = elfshname(".plt")
2106		sh.Type = uint32(elf.SHT_PROGBITS)
2107		sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
2108		if elf.Machine(eh.Machine) == elf.EM_X86_64 {
2109			sh.Entsize = 16
2110		} else if elf.Machine(eh.Machine) == elf.EM_S390 {
2111			sh.Entsize = 32
2112		} else if elf.Machine(eh.Machine) == elf.EM_PPC64 {
2113			// On ppc64, this is just a table of addresses
2114			// filled by the dynamic linker
2115			sh.Type = uint32(elf.SHT_NOBITS)
2116
2117			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2118			sh.Entsize = 8
2119		} else {
2120			sh.Entsize = 4
2121		}
2122		sh.Addralign = sh.Entsize
2123		shsym(sh, ldr, ldr.Lookup(".plt", 0))
2124
2125		// On ppc64, .got comes from the input files, so don't
2126		// create it here, and .got.plt is not used.
2127		if elf.Machine(eh.Machine) != elf.EM_PPC64 {
2128			sh := elfshname(".got")
2129			sh.Type = uint32(elf.SHT_PROGBITS)
2130			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2131			sh.Entsize = uint64(ctxt.Arch.RegSize)
2132			sh.Addralign = uint64(ctxt.Arch.RegSize)
2133			shsym(sh, ldr, ldr.Lookup(".got", 0))
2134
2135			sh = elfshname(".got.plt")
2136			sh.Type = uint32(elf.SHT_PROGBITS)
2137			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2138			sh.Entsize = uint64(ctxt.Arch.RegSize)
2139			sh.Addralign = uint64(ctxt.Arch.RegSize)
2140			shsym(sh, ldr, ldr.Lookup(".got.plt", 0))
2141		}
2142
2143		sh = elfshname(".hash")
2144		sh.Type = uint32(elf.SHT_HASH)
2145		sh.Flags = uint64(elf.SHF_ALLOC)
2146		sh.Entsize = 4
2147		sh.Addralign = uint64(ctxt.Arch.RegSize)
2148		sh.Link = uint32(elfshname(".dynsym").shnum)
2149		shsym(sh, ldr, ldr.Lookup(".hash", 0))
2150
2151		/* sh and elf.PT_DYNAMIC for .dynamic section */
2152		sh = elfshname(".dynamic")
2153
2154		sh.Type = uint32(elf.SHT_DYNAMIC)
2155		sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2156		sh.Entsize = 2 * uint64(ctxt.Arch.RegSize)
2157		sh.Addralign = uint64(ctxt.Arch.RegSize)
2158		sh.Link = uint32(elfshname(".dynstr").shnum)
2159		shsym(sh, ldr, ldr.Lookup(".dynamic", 0))
2160		ph := newElfPhdr()
2161		ph.Type = elf.PT_DYNAMIC
2162		ph.Flags = elf.PF_R + elf.PF_W
2163		phsh(ph, sh)
2164
2165		/*
2166		 * Thread-local storage segment (really just size).
2167		 */
2168		tlssize := uint64(0)
2169		for _, sect := range Segdata.Sections {
2170			if sect.Name == ".tbss" {
2171				tlssize = sect.Length
2172			}
2173		}
2174		if tlssize != 0 {
2175			ph := newElfPhdr()
2176			ph.Type = elf.PT_TLS
2177			ph.Flags = elf.PF_R
2178			ph.Memsz = tlssize
2179			ph.Align = uint64(ctxt.Arch.RegSize)
2180		}
2181	}
2182
2183	if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd {
2184		ph := newElfPhdr()
2185		ph.Type = elf.PT_GNU_STACK
2186		ph.Flags = elf.PF_W + elf.PF_R
2187		ph.Align = uint64(ctxt.Arch.RegSize)
2188	} else if ctxt.HeadType == objabi.Hopenbsd {
2189		ph := newElfPhdr()
2190		ph.Type = elf.PT_OPENBSD_NOBTCFI
2191		ph.Flags = elf.PF_X
2192	} else if ctxt.HeadType == objabi.Hsolaris {
2193		ph := newElfPhdr()
2194		ph.Type = elf.PT_SUNWSTACK
2195		ph.Flags = elf.PF_W + elf.PF_R
2196	}
2197
2198elfobj:
2199	sh := elfshname(".shstrtab")
2200	eh.Shstrndx = uint16(sh.shnum)
2201
2202	if ctxt.IsMIPS() {
2203		sh = elfshname(".MIPS.abiflags")
2204		sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
2205		sh.Flags = uint64(elf.SHF_ALLOC)
2206		sh.Addralign = 8
2207		resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff)))
2208
2209		ph := newElfPhdr()
2210		ph.Type = elf.PT_MIPS_ABIFLAGS
2211		ph.Flags = elf.PF_R
2212		phsh(ph, sh)
2213
2214		sh = elfshname(".gnu.attributes")
2215		sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES)
2216		sh.Addralign = 1
2217		ldr := ctxt.loader
2218		shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0))
2219	}
2220
2221	// put these sections early in the list
2222	if !*FlagS {
2223		elfshname(".symtab")
2224		elfshname(".strtab")
2225	}
2226	elfshname(".shstrtab")
2227
2228	for _, sect := range Segtext.Sections {
2229		elfshbits(ctxt.LinkMode, sect)
2230	}
2231	for _, sect := range Segrodata.Sections {
2232		elfshbits(ctxt.LinkMode, sect)
2233	}
2234	for _, sect := range Segrelrodata.Sections {
2235		elfshbits(ctxt.LinkMode, sect)
2236	}
2237	for _, sect := range Segdata.Sections {
2238		elfshbits(ctxt.LinkMode, sect)
2239	}
2240	for _, sect := range Segdwarf.Sections {
2241		elfshbits(ctxt.LinkMode, sect)
2242	}
2243
2244	if ctxt.LinkMode == LinkExternal {
2245		for _, sect := range Segtext.Sections {
2246			elfshreloc(ctxt.Arch, sect)
2247		}
2248		for _, sect := range Segrodata.Sections {
2249			elfshreloc(ctxt.Arch, sect)
2250		}
2251		for _, sect := range Segrelrodata.Sections {
2252			elfshreloc(ctxt.Arch, sect)
2253		}
2254		for _, sect := range Segdata.Sections {
2255			elfshreloc(ctxt.Arch, sect)
2256		}
2257		for _, si := range dwarfp {
2258			sect := ldr.SymSect(si.secSym())
2259			elfshreloc(ctxt.Arch, sect)
2260		}
2261		// add a .note.GNU-stack section to mark the stack as non-executable
2262		sh := elfshname(".note.GNU-stack")
2263
2264		sh.Type = uint32(elf.SHT_PROGBITS)
2265		sh.Addralign = 1
2266		sh.Flags = 0
2267	}
2268
2269	var shstroff uint64
2270	if !*FlagS {
2271		sh := elfshname(".symtab")
2272		sh.Type = uint32(elf.SHT_SYMTAB)
2273		sh.Off = uint64(symo)
2274		sh.Size = uint64(symSize)
2275		sh.Addralign = uint64(ctxt.Arch.RegSize)
2276		sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
2277		sh.Link = uint32(elfshname(".strtab").shnum)
2278		sh.Info = uint32(elfglobalsymndx)
2279
2280		sh = elfshname(".strtab")
2281		sh.Type = uint32(elf.SHT_STRTAB)
2282		sh.Off = uint64(symo) + uint64(symSize)
2283		sh.Size = uint64(len(elfstrdat))
2284		sh.Addralign = 1
2285		shstroff = sh.Off + sh.Size
2286	} else {
2287		shstroff = uint64(symo)
2288	}
2289
2290	sh = elfshname(".shstrtab")
2291	sh.Type = uint32(elf.SHT_STRTAB)
2292	sh.Off = shstroff
2293	sh.Size = uint64(len(elfshstrdat))
2294	sh.Addralign = 1
2295
2296	/* Main header */
2297	copy(eh.Ident[:], elf.ELFMAG)
2298
2299	var osabi elf.OSABI
2300	switch ctxt.HeadType {
2301	case objabi.Hfreebsd:
2302		osabi = elf.ELFOSABI_FREEBSD
2303	case objabi.Hnetbsd:
2304		osabi = elf.ELFOSABI_NETBSD
2305	case objabi.Hopenbsd:
2306		osabi = elf.ELFOSABI_OPENBSD
2307	case objabi.Hdragonfly:
2308		osabi = elf.ELFOSABI_NONE
2309	}
2310	eh.Ident[elf.EI_OSABI] = byte(osabi)
2311
2312	if elf64 {
2313		eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64)
2314	} else {
2315		eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32)
2316	}
2317	if ctxt.Arch.ByteOrder == binary.BigEndian {
2318		eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB)
2319	} else {
2320		eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB)
2321	}
2322	eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT)
2323
2324	if ctxt.LinkMode == LinkExternal {
2325		eh.Type = uint16(elf.ET_REL)
2326	} else if ctxt.BuildMode == BuildModePIE {
2327		eh.Type = uint16(elf.ET_DYN)
2328	} else {
2329		eh.Type = uint16(elf.ET_EXEC)
2330	}
2331
2332	if ctxt.LinkMode != LinkExternal {
2333		eh.Entry = uint64(Entryvalue(ctxt))
2334	}
2335
2336	eh.Version = uint32(elf.EV_CURRENT)
2337
2338	if pph != nil {
2339		pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize)
2340		pph.Memsz = pph.Filesz
2341	}
2342
2343	ctxt.Out.SeekSet(0)
2344	a := int64(0)
2345	a += int64(elfwritehdr(ctxt.Out))
2346	a += int64(elfwritephdrs(ctxt.Out))
2347	a += int64(elfwriteshdrs(ctxt.Out))
2348	if !*FlagD {
2349		a += int64(elfwriteinterp(ctxt.Out))
2350	}
2351	if ctxt.IsMIPS() {
2352		a += int64(elfWriteMipsAbiFlags(ctxt))
2353	}
2354
2355	if ctxt.LinkMode != LinkExternal {
2356		if ctxt.HeadType == objabi.Hnetbsd {
2357			a += int64(elfwritenetbsdsig(ctxt.Out))
2358		}
2359		if ctxt.HeadType == objabi.Hopenbsd {
2360			a += int64(elfwriteopenbsdsig(ctxt.Out))
2361		}
2362		if ctxt.HeadType == objabi.Hfreebsd {
2363			a += int64(elfwritefreebsdsig(ctxt.Out))
2364		}
2365		if len(buildinfo) > 0 {
2366			a += int64(elfwritebuildinfo(ctxt.Out))
2367		}
2368		if *flagBuildid != "" {
2369			a += int64(elfwritegobuildid(ctxt.Out))
2370		}
2371	}
2372	if *flagRace && ctxt.IsNetbsd() {
2373		a += int64(elfwritenetbsdpax(ctxt.Out))
2374	}
2375
2376	if a > elfreserve {
2377		Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
2378	}
2379
2380	// Verify the amount of space allocated for the elf header is sufficient.  The file offsets are
2381	// already computed in layout, so we could spill into another section.
2382	if a > int64(HEADR) {
2383		Errorf(nil, "HEADR too small: %d > %d with %d text sections", a, HEADR, numtext)
2384	}
2385}
2386
2387func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
2388	ldr.SetSymDynid(s, int32(Nelfsym))
2389	Nelfsym++
2390	d := ldr.MakeSymbolUpdater(syms.DynSym)
2391	name := ldr.SymExtname(s)
2392	dstru := ldr.MakeSymbolUpdater(syms.DynStr)
2393	st := ldr.SymType(s)
2394	cgoeStatic := ldr.AttrCgoExportStatic(s)
2395	cgoeDynamic := ldr.AttrCgoExportDynamic(s)
2396	cgoexp := (cgoeStatic || cgoeDynamic)
2397
2398	d.AddUint32(target.Arch, uint32(dstru.Addstring(name)))
2399
2400	if elf64 {
2401
2402		/* type */
2403		var t uint8
2404
2405		if cgoexp && st == sym.STEXT {
2406			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2407		} else {
2408			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
2409		}
2410		d.AddUint8(t)
2411
2412		/* reserved */
2413		d.AddUint8(0)
2414
2415		/* section where symbol is defined */
2416		if st == sym.SDYNIMPORT {
2417			d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
2418		} else {
2419			d.AddUint16(target.Arch, 1)
2420		}
2421
2422		/* value */
2423		if st == sym.SDYNIMPORT {
2424			d.AddUint64(target.Arch, 0)
2425		} else {
2426			d.AddAddrPlus(target.Arch, s, 0)
2427		}
2428
2429		/* size of object */
2430		d.AddUint64(target.Arch, uint64(len(ldr.Data(s))))
2431
2432		dil := ldr.SymDynimplib(s)
2433
2434		if !cgoeDynamic && dil != "" && !seenlib[dil] {
2435			du := ldr.MakeSymbolUpdater(syms.Dynamic)
2436			Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil)))
2437			seenlib[dil] = true
2438		}
2439	} else {
2440
2441		/* value */
2442		if st == sym.SDYNIMPORT {
2443			d.AddUint32(target.Arch, 0)
2444		} else {
2445			d.AddAddrPlus(target.Arch, s, 0)
2446		}
2447
2448		/* size of object */
2449		d.AddUint32(target.Arch, uint32(len(ldr.Data(s))))
2450
2451		/* type */
2452		var t uint8
2453
2454		// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
2455		if target.Arch.Family == sys.I386 && cgoexp && st == sym.STEXT {
2456			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2457		} else if target.Arch.Family == sys.ARM && cgoeDynamic && st == sym.STEXT {
2458			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2459		} else {
2460			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
2461		}
2462		d.AddUint8(t)
2463		d.AddUint8(0)
2464
2465		/* shndx */
2466		if st == sym.SDYNIMPORT {
2467			d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
2468		} else {
2469			d.AddUint16(target.Arch, 1)
2470		}
2471	}
2472}
2473