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