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