]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/ld/macho.go
all: use ":" for compiler generated symbols
[gostls13.git] / src / cmd / link / internal / ld / macho.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         "bytes"
9         "cmd/internal/codesign"
10         "cmd/internal/objabi"
11         "cmd/internal/sys"
12         "cmd/link/internal/loader"
13         "cmd/link/internal/sym"
14         "debug/macho"
15         "encoding/binary"
16         "fmt"
17         "internal/buildcfg"
18         "io"
19         "os"
20         "sort"
21         "strings"
22         "unsafe"
23 )
24
25 type MachoHdr struct {
26         cpu    uint32
27         subcpu uint32
28 }
29
30 type MachoSect struct {
31         name    string
32         segname string
33         addr    uint64
34         size    uint64
35         off     uint32
36         align   uint32
37         reloc   uint32
38         nreloc  uint32
39         flag    uint32
40         res1    uint32
41         res2    uint32
42 }
43
44 type MachoSeg struct {
45         name       string
46         vsize      uint64
47         vaddr      uint64
48         fileoffset uint64
49         filesize   uint64
50         prot1      uint32
51         prot2      uint32
52         nsect      uint32
53         msect      uint32
54         sect       []MachoSect
55         flag       uint32
56 }
57
58 // MachoPlatformLoad represents a LC_VERSION_MIN_* or
59 // LC_BUILD_VERSION load command.
60 type MachoPlatformLoad struct {
61         platform MachoPlatform // One of PLATFORM_* constants.
62         cmd      MachoLoad
63 }
64
65 type MachoLoad struct {
66         type_ uint32
67         data  []uint32
68 }
69
70 type MachoPlatform int
71
72 /*
73  * Total amount of space to reserve at the start of the file
74  * for Header, PHeaders, and SHeaders.
75  * May waste some.
76  */
77 const (
78         INITIAL_MACHO_HEADR = 4 * 1024
79 )
80
81 const (
82         MACHO_CPU_AMD64                      = 1<<24 | 7
83         MACHO_CPU_386                        = 7
84         MACHO_SUBCPU_X86                     = 3
85         MACHO_CPU_ARM                        = 12
86         MACHO_SUBCPU_ARM                     = 0
87         MACHO_SUBCPU_ARMV7                   = 9
88         MACHO_CPU_ARM64                      = 1<<24 | 12
89         MACHO_SUBCPU_ARM64_ALL               = 0
90         MACHO_SUBCPU_ARM64_V8                = 1
91         MACHO_SUBCPU_ARM64E                  = 2
92         MACHO32SYMSIZE                       = 12
93         MACHO64SYMSIZE                       = 16
94         MACHO_X86_64_RELOC_UNSIGNED          = 0
95         MACHO_X86_64_RELOC_SIGNED            = 1
96         MACHO_X86_64_RELOC_BRANCH            = 2
97         MACHO_X86_64_RELOC_GOT_LOAD          = 3
98         MACHO_X86_64_RELOC_GOT               = 4
99         MACHO_X86_64_RELOC_SUBTRACTOR        = 5
100         MACHO_X86_64_RELOC_SIGNED_1          = 6
101         MACHO_X86_64_RELOC_SIGNED_2          = 7
102         MACHO_X86_64_RELOC_SIGNED_4          = 8
103         MACHO_ARM_RELOC_VANILLA              = 0
104         MACHO_ARM_RELOC_PAIR                 = 1
105         MACHO_ARM_RELOC_SECTDIFF             = 2
106         MACHO_ARM_RELOC_BR24                 = 5
107         MACHO_ARM64_RELOC_UNSIGNED           = 0
108         MACHO_ARM64_RELOC_BRANCH26           = 2
109         MACHO_ARM64_RELOC_PAGE21             = 3
110         MACHO_ARM64_RELOC_PAGEOFF12          = 4
111         MACHO_ARM64_RELOC_GOT_LOAD_PAGE21    = 5
112         MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6
113         MACHO_ARM64_RELOC_ADDEND             = 10
114         MACHO_GENERIC_RELOC_VANILLA          = 0
115         MACHO_FAKE_GOTPCREL                  = 100
116 )
117
118 const (
119         MH_MAGIC    = 0xfeedface
120         MH_MAGIC_64 = 0xfeedfacf
121
122         MH_OBJECT  = 0x1
123         MH_EXECUTE = 0x2
124
125         MH_NOUNDEFS = 0x1
126         MH_DYLDLINK = 0x4
127         MH_PIE      = 0x200000
128 )
129
130 const (
131         LC_SEGMENT                  = 0x1
132         LC_SYMTAB                   = 0x2
133         LC_SYMSEG                   = 0x3
134         LC_THREAD                   = 0x4
135         LC_UNIXTHREAD               = 0x5
136         LC_LOADFVMLIB               = 0x6
137         LC_IDFVMLIB                 = 0x7
138         LC_IDENT                    = 0x8
139         LC_FVMFILE                  = 0x9
140         LC_PREPAGE                  = 0xa
141         LC_DYSYMTAB                 = 0xb
142         LC_LOAD_DYLIB               = 0xc
143         LC_ID_DYLIB                 = 0xd
144         LC_LOAD_DYLINKER            = 0xe
145         LC_ID_DYLINKER              = 0xf
146         LC_PREBOUND_DYLIB           = 0x10
147         LC_ROUTINES                 = 0x11
148         LC_SUB_FRAMEWORK            = 0x12
149         LC_SUB_UMBRELLA             = 0x13
150         LC_SUB_CLIENT               = 0x14
151         LC_SUB_LIBRARY              = 0x15
152         LC_TWOLEVEL_HINTS           = 0x16
153         LC_PREBIND_CKSUM            = 0x17
154         LC_LOAD_WEAK_DYLIB          = 0x80000018
155         LC_SEGMENT_64               = 0x19
156         LC_ROUTINES_64              = 0x1a
157         LC_UUID                     = 0x1b
158         LC_RPATH                    = 0x8000001c
159         LC_CODE_SIGNATURE           = 0x1d
160         LC_SEGMENT_SPLIT_INFO       = 0x1e
161         LC_REEXPORT_DYLIB           = 0x8000001f
162         LC_LAZY_LOAD_DYLIB          = 0x20
163         LC_ENCRYPTION_INFO          = 0x21
164         LC_DYLD_INFO                = 0x22
165         LC_DYLD_INFO_ONLY           = 0x80000022
166         LC_LOAD_UPWARD_DYLIB        = 0x80000023
167         LC_VERSION_MIN_MACOSX       = 0x24
168         LC_VERSION_MIN_IPHONEOS     = 0x25
169         LC_FUNCTION_STARTS          = 0x26
170         LC_DYLD_ENVIRONMENT         = 0x27
171         LC_MAIN                     = 0x80000028
172         LC_DATA_IN_CODE             = 0x29
173         LC_SOURCE_VERSION           = 0x2A
174         LC_DYLIB_CODE_SIGN_DRS      = 0x2B
175         LC_ENCRYPTION_INFO_64       = 0x2C
176         LC_LINKER_OPTION            = 0x2D
177         LC_LINKER_OPTIMIZATION_HINT = 0x2E
178         LC_VERSION_MIN_TVOS         = 0x2F
179         LC_VERSION_MIN_WATCHOS      = 0x30
180         LC_VERSION_NOTE             = 0x31
181         LC_BUILD_VERSION            = 0x32
182         LC_DYLD_EXPORTS_TRIE        = 0x80000033
183         LC_DYLD_CHAINED_FIXUPS      = 0x80000034
184 )
185
186 const (
187         S_REGULAR                  = 0x0
188         S_ZEROFILL                 = 0x1
189         S_NON_LAZY_SYMBOL_POINTERS = 0x6
190         S_SYMBOL_STUBS             = 0x8
191         S_MOD_INIT_FUNC_POINTERS   = 0x9
192         S_ATTR_PURE_INSTRUCTIONS   = 0x80000000
193         S_ATTR_DEBUG               = 0x02000000
194         S_ATTR_SOME_INSTRUCTIONS   = 0x00000400
195 )
196
197 const (
198         PLATFORM_MACOS    MachoPlatform = 1
199         PLATFORM_IOS      MachoPlatform = 2
200         PLATFORM_TVOS     MachoPlatform = 3
201         PLATFORM_WATCHOS  MachoPlatform = 4
202         PLATFORM_BRIDGEOS MachoPlatform = 5
203 )
204
205 // rebase table opcode
206 const (
207         REBASE_TYPE_POINTER         = 1
208         REBASE_TYPE_TEXT_ABSOLUTE32 = 2
209         REBASE_TYPE_TEXT_PCREL32    = 3
210
211         REBASE_OPCODE_MASK                               = 0xF0
212         REBASE_IMMEDIATE_MASK                            = 0x0F
213         REBASE_OPCODE_DONE                               = 0x00
214         REBASE_OPCODE_SET_TYPE_IMM                       = 0x10
215         REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB        = 0x20
216         REBASE_OPCODE_ADD_ADDR_ULEB                      = 0x30
217         REBASE_OPCODE_ADD_ADDR_IMM_SCALED                = 0x40
218         REBASE_OPCODE_DO_REBASE_IMM_TIMES                = 0x50
219         REBASE_OPCODE_DO_REBASE_ULEB_TIMES               = 0x60
220         REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB            = 0x70
221         REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80
222 )
223
224 // bind table opcode
225 const (
226         BIND_TYPE_POINTER         = 1
227         BIND_TYPE_TEXT_ABSOLUTE32 = 2
228         BIND_TYPE_TEXT_PCREL32    = 3
229
230         BIND_SPECIAL_DYLIB_SELF            = 0
231         BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1
232         BIND_SPECIAL_DYLIB_FLAT_LOOKUP     = -2
233         BIND_SPECIAL_DYLIB_WEAK_LOOKUP     = -3
234
235         BIND_OPCODE_MASK                                         = 0xF0
236         BIND_IMMEDIATE_MASK                                      = 0x0F
237         BIND_OPCODE_DONE                                         = 0x00
238         BIND_OPCODE_SET_DYLIB_ORDINAL_IMM                        = 0x10
239         BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB                       = 0x20
240         BIND_OPCODE_SET_DYLIB_SPECIAL_IMM                        = 0x30
241         BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM                = 0x40
242         BIND_OPCODE_SET_TYPE_IMM                                 = 0x50
243         BIND_OPCODE_SET_ADDEND_SLEB                              = 0x60
244         BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB                  = 0x70
245         BIND_OPCODE_ADD_ADDR_ULEB                                = 0x80
246         BIND_OPCODE_DO_BIND                                      = 0x90
247         BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB                        = 0xA0
248         BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED                  = 0xB0
249         BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB             = 0xC0
250         BIND_OPCODE_THREADED                                     = 0xD0
251         BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB = 0x00
252         BIND_SUBOPCODE_THREADED_APPLY                            = 0x01
253 )
254
255 const machoHeaderSize64 = 8 * 4 // size of 64-bit Mach-O header
256
257 // Mach-O file writing
258 // https://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
259
260 var machohdr MachoHdr
261
262 var load []MachoLoad
263
264 var machoPlatform MachoPlatform
265
266 var seg [16]MachoSeg
267
268 var nseg int
269
270 var ndebug int
271
272 var nsect int
273
274 const (
275         SymKindLocal = 0 + iota
276         SymKindExtdef
277         SymKindUndef
278         NumSymKind
279 )
280
281 var nkind [NumSymKind]int
282
283 var sortsym []loader.Sym
284
285 var nsortsym int
286
287 // Amount of space left for adding load commands
288 // that refer to dynamic libraries. Because these have
289 // to go in the Mach-O header, we can't just pick a
290 // "big enough" header size. The initial header is
291 // one page, the non-dynamic library stuff takes
292 // up about 1300 bytes; we overestimate that as 2k.
293 var loadBudget = INITIAL_MACHO_HEADR - 2*1024
294
295 func getMachoHdr() *MachoHdr {
296         return &machohdr
297 }
298
299 func newMachoLoad(arch *sys.Arch, type_ uint32, ndata uint32) *MachoLoad {
300         if arch.PtrSize == 8 && (ndata&1 != 0) {
301                 ndata++
302         }
303
304         load = append(load, MachoLoad{})
305         l := &load[len(load)-1]
306         l.type_ = type_
307         l.data = make([]uint32, ndata)
308         return l
309 }
310
311 func newMachoSeg(name string, msect int) *MachoSeg {
312         if nseg >= len(seg) {
313                 Exitf("too many segs")
314         }
315
316         s := &seg[nseg]
317         nseg++
318         s.name = name
319         s.msect = uint32(msect)
320         s.sect = make([]MachoSect, msect)
321         return s
322 }
323
324 func newMachoSect(seg *MachoSeg, name string, segname string) *MachoSect {
325         if seg.nsect >= seg.msect {
326                 Exitf("too many sects in segment %s", seg.name)
327         }
328
329         s := &seg.sect[seg.nsect]
330         seg.nsect++
331         s.name = name
332         s.segname = segname
333         nsect++
334         return s
335 }
336
337 // Generic linking code.
338
339 var dylib []string
340
341 var linkoff int64
342
343 func machowrite(ctxt *Link, arch *sys.Arch, out *OutBuf, linkmode LinkMode) int {
344         o1 := out.Offset()
345
346         loadsize := 4 * 4 * ndebug
347         for i := range load {
348                 loadsize += 4 * (len(load[i].data) + 2)
349         }
350         if arch.PtrSize == 8 {
351                 loadsize += 18 * 4 * nseg
352                 loadsize += 20 * 4 * nsect
353         } else {
354                 loadsize += 14 * 4 * nseg
355                 loadsize += 17 * 4 * nsect
356         }
357
358         if arch.PtrSize == 8 {
359                 out.Write32(MH_MAGIC_64)
360         } else {
361                 out.Write32(MH_MAGIC)
362         }
363         out.Write32(machohdr.cpu)
364         out.Write32(machohdr.subcpu)
365         if linkmode == LinkExternal {
366                 out.Write32(MH_OBJECT) /* file type - mach object */
367         } else {
368                 out.Write32(MH_EXECUTE) /* file type - mach executable */
369         }
370         out.Write32(uint32(len(load)) + uint32(nseg) + uint32(ndebug))
371         out.Write32(uint32(loadsize))
372         flags := uint32(0)
373         if nkind[SymKindUndef] == 0 {
374                 flags |= MH_NOUNDEFS
375         }
376         if ctxt.IsPIE() && linkmode == LinkInternal {
377                 flags |= MH_PIE | MH_DYLDLINK
378         }
379         out.Write32(flags) /* flags */
380         if arch.PtrSize == 8 {
381                 out.Write32(0) /* reserved */
382         }
383
384         for i := 0; i < nseg; i++ {
385                 s := &seg[i]
386                 if arch.PtrSize == 8 {
387                         out.Write32(LC_SEGMENT_64)
388                         out.Write32(72 + 80*s.nsect)
389                         out.WriteStringN(s.name, 16)
390                         out.Write64(s.vaddr)
391                         out.Write64(s.vsize)
392                         out.Write64(s.fileoffset)
393                         out.Write64(s.filesize)
394                         out.Write32(s.prot1)
395                         out.Write32(s.prot2)
396                         out.Write32(s.nsect)
397                         out.Write32(s.flag)
398                 } else {
399                         out.Write32(LC_SEGMENT)
400                         out.Write32(56 + 68*s.nsect)
401                         out.WriteStringN(s.name, 16)
402                         out.Write32(uint32(s.vaddr))
403                         out.Write32(uint32(s.vsize))
404                         out.Write32(uint32(s.fileoffset))
405                         out.Write32(uint32(s.filesize))
406                         out.Write32(s.prot1)
407                         out.Write32(s.prot2)
408                         out.Write32(s.nsect)
409                         out.Write32(s.flag)
410                 }
411
412                 for j := uint32(0); j < s.nsect; j++ {
413                         t := &s.sect[j]
414                         if arch.PtrSize == 8 {
415                                 out.WriteStringN(t.name, 16)
416                                 out.WriteStringN(t.segname, 16)
417                                 out.Write64(t.addr)
418                                 out.Write64(t.size)
419                                 out.Write32(t.off)
420                                 out.Write32(t.align)
421                                 out.Write32(t.reloc)
422                                 out.Write32(t.nreloc)
423                                 out.Write32(t.flag)
424                                 out.Write32(t.res1) /* reserved */
425                                 out.Write32(t.res2) /* reserved */
426                                 out.Write32(0)      /* reserved */
427                         } else {
428                                 out.WriteStringN(t.name, 16)
429                                 out.WriteStringN(t.segname, 16)
430                                 out.Write32(uint32(t.addr))
431                                 out.Write32(uint32(t.size))
432                                 out.Write32(t.off)
433                                 out.Write32(t.align)
434                                 out.Write32(t.reloc)
435                                 out.Write32(t.nreloc)
436                                 out.Write32(t.flag)
437                                 out.Write32(t.res1) /* reserved */
438                                 out.Write32(t.res2) /* reserved */
439                         }
440                 }
441         }
442
443         for i := range load {
444                 l := &load[i]
445                 out.Write32(l.type_)
446                 out.Write32(4 * (uint32(len(l.data)) + 2))
447                 for j := 0; j < len(l.data); j++ {
448                         out.Write32(l.data[j])
449                 }
450         }
451
452         return int(out.Offset() - o1)
453 }
454
455 func (ctxt *Link) domacho() {
456         if *FlagD {
457                 return
458         }
459
460         // Copy platform load command.
461         for _, h := range hostobj {
462                 load, err := hostobjMachoPlatform(&h)
463                 if err != nil {
464                         Exitf("%v", err)
465                 }
466                 if load != nil {
467                         machoPlatform = load.platform
468                         ml := newMachoLoad(ctxt.Arch, load.cmd.type_, uint32(len(load.cmd.data)))
469                         copy(ml.data, load.cmd.data)
470                         break
471                 }
472         }
473         if machoPlatform == 0 {
474                 machoPlatform = PLATFORM_MACOS
475                 if buildcfg.GOOS == "ios" {
476                         machoPlatform = PLATFORM_IOS
477                 }
478                 if ctxt.LinkMode == LinkInternal && machoPlatform == PLATFORM_MACOS {
479                         var version uint32
480                         switch ctxt.Arch.Family {
481                         case sys.AMD64:
482                                 // The version must be at least 10.9; see golang.org/issues/30488.
483                                 version = 10<<16 | 9<<8 | 0<<0 // 10.9.0
484                         case sys.ARM64:
485                                 version = 11<<16 | 0<<8 | 0<<0 // 11.0.0
486                         }
487                         ml := newMachoLoad(ctxt.Arch, LC_BUILD_VERSION, 4)
488                         ml.data[0] = uint32(machoPlatform)
489                         ml.data[1] = version // OS version
490                         ml.data[2] = version // SDK version
491                         ml.data[3] = 0       // ntools
492                 }
493         }
494
495         // empirically, string table must begin with " \x00".
496         s := ctxt.loader.LookupOrCreateSym(".machosymstr", 0)
497         sb := ctxt.loader.MakeSymbolUpdater(s)
498
499         sb.SetType(sym.SMACHOSYMSTR)
500         sb.SetReachable(true)
501         sb.AddUint8(' ')
502         sb.AddUint8('\x00')
503
504         s = ctxt.loader.LookupOrCreateSym(".machosymtab", 0)
505         sb = ctxt.loader.MakeSymbolUpdater(s)
506         sb.SetType(sym.SMACHOSYMTAB)
507         sb.SetReachable(true)
508
509         if ctxt.IsInternal() {
510                 s = ctxt.loader.LookupOrCreateSym(".plt", 0) // will be __symbol_stub
511                 sb = ctxt.loader.MakeSymbolUpdater(s)
512                 sb.SetType(sym.SMACHOPLT)
513                 sb.SetReachable(true)
514
515                 s = ctxt.loader.LookupOrCreateSym(".got", 0) // will be __nl_symbol_ptr
516                 sb = ctxt.loader.MakeSymbolUpdater(s)
517                 sb.SetType(sym.SMACHOGOT)
518                 sb.SetReachable(true)
519                 sb.SetAlign(4)
520
521                 s = ctxt.loader.LookupOrCreateSym(".linkedit.plt", 0) // indirect table for .plt
522                 sb = ctxt.loader.MakeSymbolUpdater(s)
523                 sb.SetType(sym.SMACHOINDIRECTPLT)
524                 sb.SetReachable(true)
525
526                 s = ctxt.loader.LookupOrCreateSym(".linkedit.got", 0) // indirect table for .got
527                 sb = ctxt.loader.MakeSymbolUpdater(s)
528                 sb.SetType(sym.SMACHOINDIRECTGOT)
529                 sb.SetReachable(true)
530         }
531
532         // Add a dummy symbol that will become the __asm marker section.
533         if ctxt.IsExternal() {
534                 s = ctxt.loader.LookupOrCreateSym(".llvmasm", 0)
535                 sb = ctxt.loader.MakeSymbolUpdater(s)
536                 sb.SetType(sym.SMACHO)
537                 sb.SetReachable(true)
538                 sb.AddUint8(0)
539         }
540
541         // Un-export runtime symbols from plugins. Since the runtime
542         // is included in both the main binary and each plugin, these
543         // symbols appear in both images. If we leave them exported in
544         // the plugin, then the dynamic linker will resolve
545         // relocations to these functions in the plugin's functab to
546         // point to the main image, causing the runtime to think the
547         // plugin's functab is corrupted. By unexporting them, these
548         // become static references, which are resolved to the
549         // plugin's text.
550         //
551         // It would be better to omit the runtime from plugins. (Using
552         // relative PCs in the functab instead of relocations would
553         // also address this.)
554         //
555         // See issue #18190.
556         if ctxt.BuildMode == BuildModePlugin {
557                 for _, name := range []string{"_cgo_topofstack", "__cgo_topofstack", "_cgo_panic", "crosscall2"} {
558                         // Most of these are data symbols or C
559                         // symbols, so they have symbol version 0.
560                         ver := 0
561                         // _cgo_panic is a Go function, so it uses ABIInternal.
562                         if name == "_cgo_panic" {
563                                 ver = abiInternalVer
564                         }
565                         s := ctxt.loader.Lookup(name, ver)
566                         if s != 0 {
567                                 ctxt.loader.SetAttrCgoExportDynamic(s, false)
568                         }
569                 }
570         }
571 }
572
573 func machoadddynlib(lib string, linkmode LinkMode) {
574         if seenlib[lib] || linkmode == LinkExternal {
575                 return
576         }
577         seenlib[lib] = true
578
579         // Will need to store the library name rounded up
580         // and 24 bytes of header metadata. If not enough
581         // space, grab another page of initial space at the
582         // beginning of the output file.
583         loadBudget -= (len(lib)+7)/8*8 + 24
584
585         if loadBudget < 0 {
586                 HEADR += 4096
587                 *FlagTextAddr += 4096
588                 loadBudget += 4096
589         }
590
591         dylib = append(dylib, lib)
592 }
593
594 func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) {
595         buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
596
597         msect := newMachoSect(mseg, buf, segname)
598
599         if sect.Rellen > 0 {
600                 msect.reloc = uint32(sect.Reloff)
601                 msect.nreloc = uint32(sect.Rellen / 8)
602         }
603
604         for 1<<msect.align < sect.Align {
605                 msect.align++
606         }
607         msect.addr = sect.Vaddr
608         msect.size = sect.Length
609
610         if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
611                 // data in file
612                 if sect.Length > sect.Seg.Vaddr+sect.Seg.Filelen-sect.Vaddr {
613                         Errorf(nil, "macho cannot represent section %s crossing data and bss", sect.Name)
614                 }
615                 msect.off = uint32(sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr)
616         } else {
617                 msect.off = 0
618                 msect.flag |= S_ZEROFILL
619         }
620
621         if sect.Rwx&1 != 0 {
622                 msect.flag |= S_ATTR_SOME_INSTRUCTIONS
623         }
624
625         if sect.Name == ".text" {
626                 msect.flag |= S_ATTR_PURE_INSTRUCTIONS
627         }
628
629         if sect.Name == ".plt" {
630                 msect.name = "__symbol_stub1"
631                 msect.flag = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS | S_SYMBOL_STUBS
632                 msect.res1 = 0 //nkind[SymKindLocal];
633                 msect.res2 = 6
634         }
635
636         if sect.Name == ".got" {
637                 msect.name = "__nl_symbol_ptr"
638                 msect.flag = S_NON_LAZY_SYMBOL_POINTERS
639                 msect.res1 = uint32(ctxt.loader.SymSize(ctxt.ArchSyms.LinkEditPLT) / 4) /* offset into indirect symbol table */
640         }
641
642         if sect.Name == ".init_array" {
643                 msect.name = "__mod_init_func"
644                 msect.flag = S_MOD_INIT_FUNC_POINTERS
645         }
646
647         // Some platforms such as watchOS and tvOS require binaries with
648         // bitcode enabled. The Go toolchain can't output bitcode, so use
649         // a marker section in the __LLVM segment, "__asm", to tell the Apple
650         // toolchain that the Go text came from assembler and thus has no
651         // bitcode. This is not true, but Kotlin/Native, Rust and Flutter
652         // are also using this trick.
653         if sect.Name == ".llvmasm" {
654                 msect.name = "__asm"
655                 msect.segname = "__LLVM"
656         }
657
658         if segname == "__DWARF" {
659                 msect.flag |= S_ATTR_DEBUG
660         }
661 }
662
663 func asmbMacho(ctxt *Link) {
664         machlink := doMachoLink(ctxt)
665         if !*FlagS && ctxt.IsExternal() {
666                 symo := int64(Segdwarf.Fileoff + uint64(Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))) + uint64(machlink))
667                 ctxt.Out.SeekSet(symo)
668                 machoEmitReloc(ctxt)
669         }
670         ctxt.Out.SeekSet(0)
671
672         ldr := ctxt.loader
673
674         /* apple MACH */
675         va := *FlagTextAddr - int64(HEADR)
676
677         mh := getMachoHdr()
678         switch ctxt.Arch.Family {
679         default:
680                 Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
681
682         case sys.AMD64:
683                 mh.cpu = MACHO_CPU_AMD64
684                 mh.subcpu = MACHO_SUBCPU_X86
685
686         case sys.ARM64:
687                 mh.cpu = MACHO_CPU_ARM64
688                 mh.subcpu = MACHO_SUBCPU_ARM64_ALL
689         }
690
691         var ms *MachoSeg
692         if ctxt.LinkMode == LinkExternal {
693                 /* segment for entire file */
694                 ms = newMachoSeg("", 40)
695
696                 ms.fileoffset = Segtext.Fileoff
697                 ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
698                 ms.vsize = Segdwarf.Vaddr + Segdwarf.Length - Segtext.Vaddr
699         }
700
701         /* segment for zero page */
702         if ctxt.LinkMode != LinkExternal {
703                 ms = newMachoSeg("__PAGEZERO", 0)
704                 ms.vsize = uint64(va)
705         }
706
707         /* text */
708         v := Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound))
709
710         if ctxt.LinkMode != LinkExternal {
711                 ms = newMachoSeg("__TEXT", 20)
712                 ms.vaddr = uint64(va)
713                 ms.vsize = uint64(v)
714                 ms.fileoffset = 0
715                 ms.filesize = uint64(v)
716                 ms.prot1 = 7
717                 ms.prot2 = 5
718         }
719
720         for _, sect := range Segtext.Sections {
721                 machoshbits(ctxt, ms, sect, "__TEXT")
722         }
723
724         /* rodata */
725         if ctxt.LinkMode != LinkExternal && Segrelrodata.Length > 0 {
726                 ms = newMachoSeg("__DATA_CONST", 20)
727                 ms.vaddr = Segrelrodata.Vaddr
728                 ms.vsize = Segrelrodata.Length
729                 ms.fileoffset = Segrelrodata.Fileoff
730                 ms.filesize = Segrelrodata.Filelen
731                 ms.prot1 = 3
732                 ms.prot2 = 3
733                 ms.flag = 0x10 // SG_READ_ONLY
734         }
735
736         for _, sect := range Segrelrodata.Sections {
737                 machoshbits(ctxt, ms, sect, "__DATA_CONST")
738         }
739
740         /* data */
741         if ctxt.LinkMode != LinkExternal {
742                 ms = newMachoSeg("__DATA", 20)
743                 ms.vaddr = Segdata.Vaddr
744                 ms.vsize = Segdata.Length
745                 ms.fileoffset = Segdata.Fileoff
746                 ms.filesize = Segdata.Filelen
747                 ms.prot1 = 3
748                 ms.prot2 = 3
749         }
750
751         for _, sect := range Segdata.Sections {
752                 machoshbits(ctxt, ms, sect, "__DATA")
753         }
754
755         /* dwarf */
756         if !*FlagW {
757                 if ctxt.LinkMode != LinkExternal {
758                         ms = newMachoSeg("__DWARF", 20)
759                         ms.vaddr = Segdwarf.Vaddr
760                         ms.vsize = 0
761                         ms.fileoffset = Segdwarf.Fileoff
762                         ms.filesize = Segdwarf.Filelen
763                 }
764                 for _, sect := range Segdwarf.Sections {
765                         machoshbits(ctxt, ms, sect, "__DWARF")
766                 }
767         }
768
769         if ctxt.LinkMode != LinkExternal {
770                 switch ctxt.Arch.Family {
771                 default:
772                         Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
773
774                 case sys.AMD64:
775                         ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 42+2)
776                         ml.data[0] = 4                           /* thread type */
777                         ml.data[1] = 42                          /* word count */
778                         ml.data[2+32] = uint32(Entryvalue(ctxt)) /* start pc */
779                         ml.data[2+32+1] = uint32(Entryvalue(ctxt) >> 32)
780
781                 case sys.ARM64:
782                         ml := newMachoLoad(ctxt.Arch, LC_MAIN, 4)
783                         ml.data[0] = uint32(uint64(Entryvalue(ctxt)) - (Segtext.Vaddr - uint64(HEADR)))
784                         ml.data[1] = uint32((uint64(Entryvalue(ctxt)) - (Segtext.Vaddr - uint64(HEADR))) >> 32)
785                 }
786         }
787
788         var codesigOff int64
789         if !*FlagD {
790                 // must match doMachoLink below
791                 s1 := ldr.SymSize(ldr.Lookup(".machorebase", 0))
792                 s2 := ldr.SymSize(ldr.Lookup(".machobind", 0))
793                 s3 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
794                 s4 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
795                 s5 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
796                 s6 := ldr.SymSize(ldr.Lookup(".machosymstr", 0))
797                 s7 := ldr.SymSize(ldr.Lookup(".machocodesig", 0))
798
799                 if ctxt.LinkMode != LinkExternal {
800                         ms := newMachoSeg("__LINKEDIT", 0)
801                         ms.vaddr = uint64(Rnd(int64(Segdata.Vaddr+Segdata.Length), int64(*FlagRound)))
802                         ms.vsize = uint64(s1 + s2 + s3 + s4 + s5 + s6 + s7)
803                         ms.fileoffset = uint64(linkoff)
804                         ms.filesize = ms.vsize
805                         ms.prot1 = 1
806                         ms.prot2 = 1
807
808                         codesigOff = linkoff + s1 + s2 + s3 + s4 + s5 + s6
809                 }
810
811                 if ctxt.LinkMode != LinkExternal && ctxt.IsPIE() {
812                         ml := newMachoLoad(ctxt.Arch, LC_DYLD_INFO_ONLY, 10)
813                         ml.data[0] = uint32(linkoff)      // rebase off
814                         ml.data[1] = uint32(s1)           // rebase size
815                         ml.data[2] = uint32(linkoff + s1) // bind off
816                         ml.data[3] = uint32(s2)           // bind size
817                         ml.data[4] = 0                    // weak bind off
818                         ml.data[5] = 0                    // weak bind size
819                         ml.data[6] = 0                    // lazy bind off
820                         ml.data[7] = 0                    // lazy bind size
821                         ml.data[8] = 0                    // export
822                         ml.data[9] = 0                    // export size
823                 }
824
825                 ml := newMachoLoad(ctxt.Arch, LC_SYMTAB, 4)
826                 ml.data[0] = uint32(linkoff + s1 + s2)                /* symoff */
827                 ml.data[1] = uint32(nsortsym)                         /* nsyms */
828                 ml.data[2] = uint32(linkoff + s1 + s2 + s3 + s4 + s5) /* stroff */
829                 ml.data[3] = uint32(s6)                               /* strsize */
830
831                 machodysymtab(ctxt, linkoff+s1+s2)
832
833                 if ctxt.LinkMode != LinkExternal {
834                         ml := newMachoLoad(ctxt.Arch, LC_LOAD_DYLINKER, 6)
835                         ml.data[0] = 12 /* offset to string */
836                         stringtouint32(ml.data[1:], "/usr/lib/dyld")
837
838                         for _, lib := range dylib {
839                                 ml = newMachoLoad(ctxt.Arch, LC_LOAD_DYLIB, 4+(uint32(len(lib))+1+7)/8*2)
840                                 ml.data[0] = 24 /* offset of string from beginning of load */
841                                 ml.data[1] = 0  /* time stamp */
842                                 ml.data[2] = 0  /* version */
843                                 ml.data[3] = 0  /* compatibility version */
844                                 stringtouint32(ml.data[4:], lib)
845                         }
846                 }
847
848                 if ctxt.IsInternal() && ctxt.NeedCodeSign() {
849                         ml := newMachoLoad(ctxt.Arch, LC_CODE_SIGNATURE, 2)
850                         ml.data[0] = uint32(codesigOff)
851                         ml.data[1] = uint32(s7)
852                 }
853         }
854
855         a := machowrite(ctxt, ctxt.Arch, ctxt.Out, ctxt.LinkMode)
856         if int32(a) > HEADR {
857                 Exitf("HEADR too small: %d > %d", a, HEADR)
858         }
859
860         // Now we have written everything. Compute the code signature (which
861         // is a hash of the file content, so it must be done at last.)
862         if ctxt.IsInternal() && ctxt.NeedCodeSign() {
863                 cs := ldr.Lookup(".machocodesig", 0)
864                 data := ctxt.Out.Data()
865                 if int64(len(data)) != codesigOff {
866                         panic("wrong size")
867                 }
868                 codesign.Sign(ldr.Data(cs), bytes.NewReader(data), "a.out", codesigOff, int64(Segtext.Fileoff), int64(Segtext.Filelen), ctxt.IsExe() || ctxt.IsPIE())
869                 ctxt.Out.SeekSet(codesigOff)
870                 ctxt.Out.Write(ldr.Data(cs))
871         }
872 }
873
874 func symkind(ldr *loader.Loader, s loader.Sym) int {
875         if ldr.SymType(s) == sym.SDYNIMPORT {
876                 return SymKindUndef
877         }
878         if ldr.AttrCgoExport(s) {
879                 return SymKindExtdef
880         }
881         return SymKindLocal
882 }
883
884 func collectmachosyms(ctxt *Link) {
885         ldr := ctxt.loader
886
887         addsym := func(s loader.Sym) {
888                 sortsym = append(sortsym, s)
889                 nkind[symkind(ldr, s)]++
890         }
891
892         // Add special runtime.text and runtime.etext symbols.
893         // We've already included this symbol in Textp on darwin if ctxt.DynlinkingGo().
894         // See data.go:/textaddress
895         if !ctxt.DynlinkingGo() {
896                 s := ldr.Lookup("runtime.text", 0)
897                 if ldr.SymType(s) == sym.STEXT {
898                         addsym(s)
899                 }
900                 for n := range Segtext.Sections[1:] {
901                         s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0)
902                         if s != 0 {
903                                 addsym(s)
904                         } else {
905                                 break
906                         }
907                 }
908                 s = ldr.Lookup("runtime.etext", 0)
909                 if ldr.SymType(s) == sym.STEXT {
910                         addsym(s)
911                 }
912         }
913
914         // Add text symbols.
915         for _, s := range ctxt.Textp {
916                 addsym(s)
917         }
918
919         shouldBeInSymbolTable := func(s loader.Sym) bool {
920                 if ldr.AttrNotInSymbolTable(s) {
921                         return false
922                 }
923                 name := ldr.SymName(s) // TODO: try not to read the name
924                 if name == "" || name[0] == '.' {
925                         return false
926                 }
927                 return true
928         }
929
930         // Add data symbols and external references.
931         for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
932                 if !ldr.AttrReachable(s) {
933                         continue
934                 }
935                 t := ldr.SymType(s)
936                 if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
937                         if t == sym.STLSBSS {
938                                 // TLSBSS is not used on darwin. See data.go:allocateDataSections
939                                 continue
940                         }
941                         if !shouldBeInSymbolTable(s) {
942                                 continue
943                         }
944                         addsym(s)
945                 }
946
947                 switch t {
948                 case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
949                         addsym(s)
950                 }
951
952                 // Some 64-bit functions have a "$INODE64" or "$INODE64$UNIX2003" suffix.
953                 if t == sym.SDYNIMPORT && ldr.SymDynimplib(s) == "/usr/lib/libSystem.B.dylib" {
954                         // But only on macOS.
955                         if machoPlatform == PLATFORM_MACOS {
956                                 switch n := ldr.SymExtname(s); n {
957                                 case "fdopendir":
958                                         switch buildcfg.GOARCH {
959                                         case "amd64":
960                                                 ldr.SetSymExtname(s, n+"$INODE64")
961                                         }
962                                 case "readdir_r", "getfsstat":
963                                         switch buildcfg.GOARCH {
964                                         case "amd64":
965                                                 ldr.SetSymExtname(s, n+"$INODE64")
966                                         }
967                                 }
968                         }
969                 }
970         }
971
972         nsortsym = len(sortsym)
973 }
974
975 func machosymorder(ctxt *Link) {
976         ldr := ctxt.loader
977
978         // On Mac OS X Mountain Lion, we must sort exported symbols
979         // So we sort them here and pre-allocate dynid for them
980         // See https://golang.org/issue/4029
981         for _, s := range ctxt.dynexp {
982                 if !ldr.AttrReachable(s) {
983                         panic("dynexp symbol is not reachable")
984                 }
985         }
986         collectmachosyms(ctxt)
987         sort.Slice(sortsym[:nsortsym], func(i, j int) bool {
988                 s1 := sortsym[i]
989                 s2 := sortsym[j]
990                 k1 := symkind(ldr, s1)
991                 k2 := symkind(ldr, s2)
992                 if k1 != k2 {
993                         return k1 < k2
994                 }
995                 return ldr.SymExtname(s1) < ldr.SymExtname(s2) // Note: unnamed symbols are not added in collectmachosyms
996         })
997         for i, s := range sortsym {
998                 ldr.SetSymDynid(s, int32(i))
999         }
1000 }
1001
1002 // AddMachoSym adds s to Mach-O symbol table, used in GenSymLate.
1003 // Currently only used on ARM64 when external linking.
1004 func AddMachoSym(ldr *loader.Loader, s loader.Sym) {
1005         ldr.SetSymDynid(s, int32(nsortsym))
1006         sortsym = append(sortsym, s)
1007         nsortsym++
1008         nkind[symkind(ldr, s)]++
1009 }
1010
1011 // machoShouldExport reports whether a symbol needs to be exported.
1012 //
1013 // When dynamically linking, all non-local variables and plugin-exported
1014 // symbols need to be exported.
1015 func machoShouldExport(ctxt *Link, ldr *loader.Loader, s loader.Sym) bool {
1016         if !ctxt.DynlinkingGo() || ldr.AttrLocal(s) {
1017                 return false
1018         }
1019         if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(ldr.SymExtname(s), objabi.PathToPrefix(*flagPluginPath)) {
1020                 return true
1021         }
1022         name := ldr.SymName(s)
1023         if strings.HasPrefix(name, "go:itab.") {
1024                 return true
1025         }
1026         if strings.HasPrefix(name, "type:") && !strings.HasPrefix(name, "type:.") {
1027                 // reduce runtime typemap pressure, but do not
1028                 // export alg functions (type:.*), as these
1029                 // appear in pclntable.
1030                 return true
1031         }
1032         if strings.HasPrefix(name, "go:link.pkghash") {
1033                 return true
1034         }
1035         return ldr.SymType(s) >= sym.SFirstWritable // only writable sections
1036 }
1037
1038 func machosymtab(ctxt *Link) {
1039         ldr := ctxt.loader
1040         symtab := ldr.CreateSymForUpdate(".machosymtab", 0)
1041         symstr := ldr.CreateSymForUpdate(".machosymstr", 0)
1042
1043         for _, s := range sortsym[:nsortsym] {
1044                 symtab.AddUint32(ctxt.Arch, uint32(symstr.Size()))
1045
1046                 export := machoShouldExport(ctxt, ldr, s)
1047
1048                 // Prefix symbol names with "_" to match the system toolchain.
1049                 // (We used to only prefix C symbols, which is all required for the build.
1050                 // But some tools don't recognize Go symbols as symbols, so we prefix them
1051                 // as well.)
1052                 symstr.AddUint8('_')
1053
1054                 // replace "·" as ".", because DTrace cannot handle it.
1055                 name := strings.Replace(ldr.SymExtname(s), "·", ".", -1)
1056
1057                 name = mangleABIName(ctxt, ldr, s, name)
1058                 symstr.Addstring(name)
1059
1060                 if t := ldr.SymType(s); t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {
1061                         symtab.AddUint8(0x01)                             // type N_EXT, external symbol
1062                         symtab.AddUint8(0)                                // no section
1063                         symtab.AddUint16(ctxt.Arch, 0)                    // desc
1064                         symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value
1065                 } else {
1066                         if export || ldr.AttrCgoExportDynamic(s) {
1067                                 symtab.AddUint8(0x0f) // N_SECT | N_EXT
1068                         } else if ldr.AttrCgoExportStatic(s) {
1069                                 // Only export statically, not dynamically. (N_PEXT is like hidden visibility)
1070                                 symtab.AddUint8(0x1f) // N_SECT | N_EXT | N_PEXT
1071                         } else {
1072                                 symtab.AddUint8(0x0e) // N_SECT
1073                         }
1074                         o := s
1075                         if outer := ldr.OuterSym(o); outer != 0 {
1076                                 o = outer
1077                         }
1078                         if ldr.SymSect(o) == nil {
1079                                 ldr.Errorf(s, "missing section for symbol")
1080                                 symtab.AddUint8(0)
1081                         } else {
1082                                 symtab.AddUint8(uint8(ldr.SymSect(o).Extnum))
1083                         }
1084                         symtab.AddUint16(ctxt.Arch, 0) // desc
1085                         symtab.AddUintXX(ctxt.Arch, uint64(ldr.SymAddr(s)), ctxt.Arch.PtrSize)
1086                 }
1087         }
1088 }
1089
1090 func machodysymtab(ctxt *Link, base int64) {
1091         ml := newMachoLoad(ctxt.Arch, LC_DYSYMTAB, 18)
1092
1093         n := 0
1094         ml.data[0] = uint32(n)                   /* ilocalsym */
1095         ml.data[1] = uint32(nkind[SymKindLocal]) /* nlocalsym */
1096         n += nkind[SymKindLocal]
1097
1098         ml.data[2] = uint32(n)                    /* iextdefsym */
1099         ml.data[3] = uint32(nkind[SymKindExtdef]) /* nextdefsym */
1100         n += nkind[SymKindExtdef]
1101
1102         ml.data[4] = uint32(n)                   /* iundefsym */
1103         ml.data[5] = uint32(nkind[SymKindUndef]) /* nundefsym */
1104
1105         ml.data[6] = 0  /* tocoffset */
1106         ml.data[7] = 0  /* ntoc */
1107         ml.data[8] = 0  /* modtaboff */
1108         ml.data[9] = 0  /* nmodtab */
1109         ml.data[10] = 0 /* extrefsymoff */
1110         ml.data[11] = 0 /* nextrefsyms */
1111
1112         ldr := ctxt.loader
1113
1114         // must match domacholink below
1115         s1 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
1116         s2 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
1117         s3 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
1118         ml.data[12] = uint32(base + s1)     /* indirectsymoff */
1119         ml.data[13] = uint32((s2 + s3) / 4) /* nindirectsyms */
1120
1121         ml.data[14] = 0 /* extreloff */
1122         ml.data[15] = 0 /* nextrel */
1123         ml.data[16] = 0 /* locreloff */
1124         ml.data[17] = 0 /* nlocrel */
1125 }
1126
1127 func doMachoLink(ctxt *Link) int64 {
1128         machosymtab(ctxt)
1129         machoDyldInfo(ctxt)
1130
1131         ldr := ctxt.loader
1132
1133         // write data that will be linkedit section
1134         s1 := ldr.Lookup(".machorebase", 0)
1135         s2 := ldr.Lookup(".machobind", 0)
1136         s3 := ldr.Lookup(".machosymtab", 0)
1137         s4 := ctxt.ArchSyms.LinkEditPLT
1138         s5 := ctxt.ArchSyms.LinkEditGOT
1139         s6 := ldr.Lookup(".machosymstr", 0)
1140
1141         size := ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4) + ldr.SymSize(s5) + ldr.SymSize(s6)
1142
1143         // Force the linkedit section to end on a 16-byte
1144         // boundary. This allows pure (non-cgo) Go binaries
1145         // to be code signed correctly.
1146         //
1147         // Apple's codesign_allocate (a helper utility for
1148         // the codesign utility) can do this fine itself if
1149         // it is run on a dynamic Mach-O binary. However,
1150         // when it is run on a pure (non-cgo) Go binary, where
1151         // the linkedit section is mostly empty, it fails to
1152         // account for the extra padding that it itself adds
1153         // when adding the LC_CODE_SIGNATURE load command
1154         // (which must be aligned on a 16-byte boundary).
1155         //
1156         // By forcing the linkedit section to end on a 16-byte
1157         // boundary, codesign_allocate will not need to apply
1158         // any alignment padding itself, working around the
1159         // issue.
1160         if size%16 != 0 {
1161                 n := 16 - size%16
1162                 s6b := ldr.MakeSymbolUpdater(s6)
1163                 s6b.Grow(s6b.Size() + n)
1164                 s6b.SetSize(s6b.Size() + n)
1165                 size += n
1166         }
1167
1168         if size > 0 {
1169                 linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segrelrodata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))
1170                 ctxt.Out.SeekSet(linkoff)
1171
1172                 ctxt.Out.Write(ldr.Data(s1))
1173                 ctxt.Out.Write(ldr.Data(s2))
1174                 ctxt.Out.Write(ldr.Data(s3))
1175                 ctxt.Out.Write(ldr.Data(s4))
1176                 ctxt.Out.Write(ldr.Data(s5))
1177                 ctxt.Out.Write(ldr.Data(s6))
1178
1179                 // Add code signature if necessary. This must be the last.
1180                 s7 := machoCodeSigSym(ctxt, linkoff+size)
1181                 size += ldr.SymSize(s7)
1182         }
1183
1184         return Rnd(size, int64(*FlagRound))
1185 }
1186
1187 func machorelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
1188         // If main section has no bits, nothing to relocate.
1189         if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1190                 return
1191         }
1192         ldr := ctxt.loader
1193
1194         for i, s := range syms {
1195                 if !ldr.AttrReachable(s) {
1196                         continue
1197                 }
1198                 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1199                         syms = syms[i:]
1200                         break
1201                 }
1202         }
1203
1204         eaddr := sect.Vaddr + sect.Length
1205         for _, s := range syms {
1206                 if !ldr.AttrReachable(s) {
1207                         continue
1208                 }
1209                 if ldr.SymValue(s) >= int64(eaddr) {
1210                         break
1211                 }
1212
1213                 // Compute external relocations on the go, and pass to Machoreloc1
1214                 // to stream out.
1215                 relocs := ldr.Relocs(s)
1216                 for ri := 0; ri < relocs.Count(); ri++ {
1217                         r := relocs.At(ri)
1218                         rr, ok := extreloc(ctxt, ldr, s, r)
1219                         if !ok {
1220                                 continue
1221                         }
1222                         if rr.Xsym == 0 {
1223                                 ldr.Errorf(s, "missing xsym in relocation")
1224                                 continue
1225                         }
1226                         if !ldr.AttrReachable(rr.Xsym) {
1227                                 ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
1228                         }
1229                         if !thearch.Machoreloc1(ctxt.Arch, out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
1230                                 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()))
1231                         }
1232                 }
1233         }
1234
1235         // sanity check
1236         if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
1237                 panic("machorelocsect: size mismatch")
1238         }
1239 }
1240
1241 func machoEmitReloc(ctxt *Link) {
1242         for ctxt.Out.Offset()&7 != 0 {
1243                 ctxt.Out.Write8(0)
1244         }
1245
1246         sizeExtRelocs(ctxt, thearch.MachorelocSize)
1247         relocSect, wg := relocSectFn(ctxt, machorelocsect)
1248
1249         relocSect(ctxt, Segtext.Sections[0], ctxt.Textp)
1250         for _, sect := range Segtext.Sections[1:] {
1251                 if sect.Name == ".text" {
1252                         relocSect(ctxt, sect, ctxt.Textp)
1253                 } else {
1254                         relocSect(ctxt, sect, ctxt.datap)
1255                 }
1256         }
1257         for _, sect := range Segrelrodata.Sections {
1258                 relocSect(ctxt, sect, ctxt.datap)
1259         }
1260         for _, sect := range Segdata.Sections {
1261                 relocSect(ctxt, sect, ctxt.datap)
1262         }
1263         for i := 0; i < len(Segdwarf.Sections); i++ {
1264                 sect := Segdwarf.Sections[i]
1265                 si := dwarfp[i]
1266                 if si.secSym() != loader.Sym(sect.Sym) ||
1267                         ctxt.loader.SymSect(si.secSym()) != sect {
1268                         panic("inconsistency between dwarfp and Segdwarf")
1269                 }
1270                 relocSect(ctxt, sect, si.syms)
1271         }
1272         wg.Wait()
1273 }
1274
1275 // hostobjMachoPlatform returns the first platform load command found
1276 // in the host object, if any.
1277 func hostobjMachoPlatform(h *Hostobj) (*MachoPlatformLoad, error) {
1278         f, err := os.Open(h.file)
1279         if err != nil {
1280                 return nil, fmt.Errorf("%s: failed to open host object: %v\n", h.file, err)
1281         }
1282         defer f.Close()
1283         sr := io.NewSectionReader(f, h.off, h.length)
1284         m, err := macho.NewFile(sr)
1285         if err != nil {
1286                 // Not a valid Mach-O file.
1287                 return nil, nil
1288         }
1289         return peekMachoPlatform(m)
1290 }
1291
1292 // peekMachoPlatform returns the first LC_VERSION_MIN_* or LC_BUILD_VERSION
1293 // load command found in the Mach-O file, if any.
1294 func peekMachoPlatform(m *macho.File) (*MachoPlatformLoad, error) {
1295         for _, cmd := range m.Loads {
1296                 raw := cmd.Raw()
1297                 ml := MachoLoad{
1298                         type_: m.ByteOrder.Uint32(raw),
1299                 }
1300                 // Skip the type and command length.
1301                 data := raw[8:]
1302                 var p MachoPlatform
1303                 switch ml.type_ {
1304                 case LC_VERSION_MIN_IPHONEOS:
1305                         p = PLATFORM_IOS
1306                 case LC_VERSION_MIN_MACOSX:
1307                         p = PLATFORM_MACOS
1308                 case LC_VERSION_MIN_WATCHOS:
1309                         p = PLATFORM_WATCHOS
1310                 case LC_VERSION_MIN_TVOS:
1311                         p = PLATFORM_TVOS
1312                 case LC_BUILD_VERSION:
1313                         p = MachoPlatform(m.ByteOrder.Uint32(data))
1314                 default:
1315                         continue
1316                 }
1317                 ml.data = make([]uint32, len(data)/4)
1318                 r := bytes.NewReader(data)
1319                 if err := binary.Read(r, m.ByteOrder, &ml.data); err != nil {
1320                         return nil, err
1321                 }
1322                 return &MachoPlatformLoad{
1323                         platform: p,
1324                         cmd:      ml,
1325                 }, nil
1326         }
1327         return nil, nil
1328 }
1329
1330 // A rebase entry tells the dynamic linker the data at sym+off needs to be
1331 // relocated when the in-memory image moves. (This is somewhat like, say,
1332 // ELF R_X86_64_RELATIVE).
1333 // For now, the only kind of entry we support is that the data is an absolute
1334 // address. That seems all we need.
1335 // In the binary it uses a compact stateful bytecode encoding. So we record
1336 // entries as we go and build the table at the end.
1337 type machoRebaseRecord struct {
1338         sym loader.Sym
1339         off int64
1340 }
1341
1342 var machorebase []machoRebaseRecord
1343
1344 func MachoAddRebase(s loader.Sym, off int64) {
1345         machorebase = append(machorebase, machoRebaseRecord{s, off})
1346 }
1347
1348 // A bind entry tells the dynamic linker the data at GOT+off should be bound
1349 // to the address of the target symbol, which is a dynamic import.
1350 // For now, the only kind of entry we support is that the data is an absolute
1351 // address, and the source symbol is always the GOT. That seems all we need.
1352 // In the binary it uses a compact stateful bytecode encoding. So we record
1353 // entries as we go and build the table at the end.
1354 type machoBindRecord struct {
1355         off  int64
1356         targ loader.Sym
1357 }
1358
1359 var machobind []machoBindRecord
1360
1361 func MachoAddBind(off int64, targ loader.Sym) {
1362         machobind = append(machobind, machoBindRecord{off, targ})
1363 }
1364
1365 // Generate data for the dynamic linker, used in LC_DYLD_INFO_ONLY load command.
1366 // See mach-o/loader.h, struct dyld_info_command, for the encoding.
1367 // e.g. https://opensource.apple.com/source/xnu/xnu-6153.81.5/EXTERNAL_HEADERS/mach-o/loader.h
1368 func machoDyldInfo(ctxt *Link) {
1369         ldr := ctxt.loader
1370         rebase := ldr.CreateSymForUpdate(".machorebase", 0)
1371         bind := ldr.CreateSymForUpdate(".machobind", 0)
1372
1373         if !(ctxt.IsPIE() && ctxt.IsInternal()) {
1374                 return
1375         }
1376
1377         segId := func(seg *sym.Segment) uint8 {
1378                 switch seg {
1379                 case &Segtext:
1380                         return 1
1381                 case &Segrelrodata:
1382                         return 2
1383                 case &Segdata:
1384                         if Segrelrodata.Length > 0 {
1385                                 return 3
1386                         }
1387                         return 2
1388                 }
1389                 panic("unknown segment")
1390         }
1391
1392         dylibId := func(s loader.Sym) int {
1393                 slib := ldr.SymDynimplib(s)
1394                 for i, lib := range dylib {
1395                         if lib == slib {
1396                                 return i + 1
1397                         }
1398                 }
1399                 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP // don't know where it is from
1400         }
1401
1402         // Rebase table.
1403         // TODO: use more compact encoding. The encoding is stateful, and
1404         // we can use delta encoding.
1405         rebase.AddUint8(REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER)
1406         for _, r := range machorebase {
1407                 seg := ldr.SymSect(r.sym).Seg
1408                 off := uint64(ldr.SymValue(r.sym)+r.off) - seg.Vaddr
1409                 rebase.AddUint8(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segId(seg))
1410                 rebase.AddUleb(off)
1411
1412                 rebase.AddUint8(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1)
1413         }
1414         rebase.AddUint8(REBASE_OPCODE_DONE)
1415         sz := Rnd(rebase.Size(), 8)
1416         rebase.Grow(sz)
1417         rebase.SetSize(sz)
1418
1419         // Bind table.
1420         // TODO: compact encoding, as above.
1421         // TODO: lazy binding?
1422         got := ctxt.GOT
1423         seg := ldr.SymSect(got).Seg
1424         gotAddr := ldr.SymValue(got)
1425         bind.AddUint8(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER)
1426         for _, r := range machobind {
1427                 off := uint64(gotAddr+r.off) - seg.Vaddr
1428                 bind.AddUint8(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segId(seg))
1429                 bind.AddUleb(off)
1430
1431                 d := dylibId(r.targ)
1432                 if d > 0 && d < 128 {
1433                         bind.AddUint8(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | uint8(d)&0xf)
1434                 } else if d >= 128 {
1435                         bind.AddUint8(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB)
1436                         bind.AddUleb(uint64(d))
1437                 } else { // d <= 0
1438                         bind.AddUint8(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | uint8(d)&0xf)
1439                 }
1440
1441                 bind.AddUint8(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
1442                 // target symbol name as a C string, with _ prefix
1443                 bind.AddUint8('_')
1444                 bind.Addstring(ldr.SymExtname(r.targ))
1445
1446                 bind.AddUint8(BIND_OPCODE_DO_BIND)
1447         }
1448         bind.AddUint8(BIND_OPCODE_DONE)
1449         sz = Rnd(bind.Size(), 16) // make it 16-byte aligned, see the comment in doMachoLink
1450         bind.Grow(sz)
1451         bind.SetSize(sz)
1452
1453         // TODO: export table.
1454         // The symbols names are encoded as a trie. I'm really too lazy to do that
1455         // for now.
1456         // Without it, the symbols are not dynamically exported, so they cannot be
1457         // e.g. dlsym'd. But internal linking is not the default in that case, so
1458         // it is fine.
1459 }
1460
1461 // machoCodeSigSym creates and returns a symbol for code signature.
1462 // The symbol context is left as zeros, which will be generated at the end
1463 // (as it depends on the rest of the file).
1464 func machoCodeSigSym(ctxt *Link, codeSize int64) loader.Sym {
1465         ldr := ctxt.loader
1466         cs := ldr.CreateSymForUpdate(".machocodesig", 0)
1467         if !ctxt.NeedCodeSign() || ctxt.IsExternal() {
1468                 return cs.Sym()
1469         }
1470         sz := codesign.Size(codeSize, "a.out")
1471         cs.Grow(sz)
1472         cs.SetSize(sz)
1473         return cs.Sym()
1474 }
1475
1476 // machoCodeSign code-signs Mach-O file fname with an ad-hoc signature.
1477 // This is used for updating an external linker generated binary.
1478 func machoCodeSign(ctxt *Link, fname string) error {
1479         f, err := os.OpenFile(fname, os.O_RDWR, 0)
1480         if err != nil {
1481                 return err
1482         }
1483         defer f.Close()
1484
1485         mf, err := macho.NewFile(f)
1486         if err != nil {
1487                 return err
1488         }
1489         if mf.Magic != macho.Magic64 {
1490                 Exitf("not 64-bit Mach-O file: %s", fname)
1491         }
1492
1493         // Find existing LC_CODE_SIGNATURE and __LINKEDIT segment
1494         var sigOff, sigSz, csCmdOff, linkeditOff int64
1495         var linkeditSeg, textSeg *macho.Segment
1496         loadOff := int64(machoHeaderSize64)
1497         get32 := mf.ByteOrder.Uint32
1498         for _, l := range mf.Loads {
1499                 data := l.Raw()
1500                 cmd, sz := get32(data), get32(data[4:])
1501                 if cmd == LC_CODE_SIGNATURE {
1502                         sigOff = int64(get32(data[8:]))
1503                         sigSz = int64(get32(data[12:]))
1504                         csCmdOff = loadOff
1505                 }
1506                 if seg, ok := l.(*macho.Segment); ok {
1507                         switch seg.Name {
1508                         case "__LINKEDIT":
1509                                 linkeditSeg = seg
1510                                 linkeditOff = loadOff
1511                         case "__TEXT":
1512                                 textSeg = seg
1513                         }
1514                 }
1515                 loadOff += int64(sz)
1516         }
1517
1518         if sigOff == 0 {
1519                 // The C linker doesn't generate a signed binary, for some reason.
1520                 // Skip.
1521                 return nil
1522         }
1523
1524         fi, err := f.Stat()
1525         if err != nil {
1526                 return err
1527         }
1528         if sigOff+sigSz != fi.Size() {
1529                 // We don't expect anything after the signature (this will invalidate
1530                 // the signature anyway.)
1531                 return fmt.Errorf("unexpected content after code signature")
1532         }
1533
1534         sz := codesign.Size(sigOff, "a.out")
1535         if sz != sigSz {
1536                 // Update the load command,
1537                 var tmp [8]byte
1538                 mf.ByteOrder.PutUint32(tmp[:4], uint32(sz))
1539                 _, err = f.WriteAt(tmp[:4], csCmdOff+12)
1540                 if err != nil {
1541                         return err
1542                 }
1543
1544                 // Uodate the __LINKEDIT segment.
1545                 segSz := sigOff + sz - int64(linkeditSeg.Offset)
1546                 mf.ByteOrder.PutUint64(tmp[:8], uint64(segSz))
1547                 _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Memsz)))
1548                 if err != nil {
1549                         return err
1550                 }
1551                 _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Filesz)))
1552                 if err != nil {
1553                         return err
1554                 }
1555         }
1556
1557         cs := make([]byte, sz)
1558         codesign.Sign(cs, f, "a.out", sigOff, int64(textSeg.Offset), int64(textSeg.Filesz), ctxt.IsExe() || ctxt.IsPIE())
1559         _, err = f.WriteAt(cs, sigOff)
1560         if err != nil {
1561                 return err
1562         }
1563         err = f.Truncate(sigOff + sz)
1564         return err
1565 }