1
2
3
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
59
60 type MachoPlatformLoad struct {
61 platform MachoPlatform
62 cmd MachoLoad
63 }
64
65 type MachoLoad struct {
66 type_ uint32
67 data []uint32
68 }
69
70 type MachoPlatform int
71
72
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
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
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
256
257
258
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
288
289
290
291
292
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
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)
367 } else {
368 out.Write32(MH_EXECUTE)
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)
380 if arch.PtrSize == 8 {
381 out.Write32(0)
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)
425 out.Write32(t.res2)
426 out.Write32(0)
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)
438 out.Write32(t.res2)
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
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
483 version = 10<<16 | 9<<8 | 0<<0
484 case sys.ARM64:
485 version = 11<<16 | 0<<8 | 0<<0
486 }
487 ml := newMachoLoad(ctxt.Arch, LC_BUILD_VERSION, 4)
488 ml.data[0] = uint32(machoPlatform)
489 ml.data[1] = version
490 ml.data[2] = version
491 ml.data[3] = 0
492 }
493 }
494
495
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)
511 sb = ctxt.loader.MakeSymbolUpdater(s)
512 sb.SetType(sym.SMACHOPLT)
513 sb.SetReachable(true)
514
515 s = ctxt.loader.LookupOrCreateSym(".got", 0)
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)
522 sb = ctxt.loader.MakeSymbolUpdater(s)
523 sb.SetType(sym.SMACHOINDIRECTPLT)
524 sb.SetReachable(true)
525
526 s = ctxt.loader.LookupOrCreateSym(".linkedit.got", 0)
527 sb = ctxt.loader.MakeSymbolUpdater(s)
528 sb.SetType(sym.SMACHOINDIRECTGOT)
529 sb.SetReachable(true)
530 }
531
532
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
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556 if ctxt.BuildMode == BuildModePlugin {
557 for _, name := range []string{"_cgo_topofstack", "__cgo_topofstack", "_cgo_panic", "crosscall2"} {
558
559
560 ver := 0
561
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
580
581
582
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
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
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)
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
648
649
650
651
652
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
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
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
702 if ctxt.LinkMode != LinkExternal {
703 ms = newMachoSeg("__PAGEZERO", 0)
704 ms.vsize = uint64(va)
705 }
706
707
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
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
734 }
735
736 for _, sect := range Segrelrodata.Sections {
737 machoshbits(ctxt, ms, sect, "__DATA_CONST")
738 }
739
740
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
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
777 ml.data[1] = 42
778 ml.data[2+32] = uint32(Entryvalue(ctxt))
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
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)
814 ml.data[1] = uint32(s1)
815 ml.data[2] = uint32(linkoff + s1)
816 ml.data[3] = uint32(s2)
817 ml.data[4] = 0
818 ml.data[5] = 0
819 ml.data[6] = 0
820 ml.data[7] = 0
821 ml.data[8] = 0
822 ml.data[9] = 0
823 }
824
825 ml := newMachoLoad(ctxt.Arch, LC_SYMTAB, 4)
826 ml.data[0] = uint32(linkoff + s1 + s2)
827 ml.data[1] = uint32(nsortsym)
828 ml.data[2] = uint32(linkoff + s1 + s2 + s3 + s4 + s5)
829 ml.data[3] = uint32(s6)
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
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
841 ml.data[1] = 0
842 ml.data[2] = 0
843 ml.data[3] = 0
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
861
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
893
894
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
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.RawSymName(s)
924 if name == "" || name[0] == '.' {
925 return false
926 }
927 return true
928 }
929
930
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 {
937 if t == sym.STLSBSS {
938
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
953 if t == sym.SDYNIMPORT && ldr.SymDynimplib(s) == "/usr/lib/libSystem.B.dylib" {
954
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
979
980
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)
996 })
997 for i, s := range sortsym {
998 ldr.SetSymDynid(s, int32(i))
999 }
1000 }
1001
1002
1003
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
1012
1013
1014
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.RawSymName(s)
1023 if strings.HasPrefix(name, "go.itab.") {
1024 return true
1025 }
1026 if strings.HasPrefix(name, "type.") && !strings.HasPrefix(name, "type..") {
1027
1028
1029
1030 return true
1031 }
1032 if strings.HasPrefix(name, "go.link.pkghash") {
1033 return true
1034 }
1035 return ldr.SymType(s) >= sym.SFirstWritable
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
1049
1050
1051
1052 symstr.AddUint8('_')
1053
1054
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)
1062 symtab.AddUint8(0)
1063 symtab.AddUint16(ctxt.Arch, 0)
1064 symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize)
1065 } else {
1066 if export || ldr.AttrCgoExportDynamic(s) {
1067 symtab.AddUint8(0x0f)
1068 } else if ldr.AttrCgoExportStatic(s) {
1069
1070 symtab.AddUint8(0x1f)
1071 } else {
1072 symtab.AddUint8(0x0e)
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)
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)
1095 ml.data[1] = uint32(nkind[SymKindLocal])
1096 n += nkind[SymKindLocal]
1097
1098 ml.data[2] = uint32(n)
1099 ml.data[3] = uint32(nkind[SymKindExtdef])
1100 n += nkind[SymKindExtdef]
1101
1102 ml.data[4] = uint32(n)
1103 ml.data[5] = uint32(nkind[SymKindUndef])
1104
1105 ml.data[6] = 0
1106 ml.data[7] = 0
1107 ml.data[8] = 0
1108 ml.data[9] = 0
1109 ml.data[10] = 0
1110 ml.data[11] = 0
1111
1112 ldr := ctxt.loader
1113
1114
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)
1119 ml.data[13] = uint32((s2 + s3) / 4)
1120
1121 ml.data[14] = 0
1122 ml.data[15] = 0
1123 ml.data[16] = 0
1124 ml.data[17] = 0
1125 }
1126
1127 func doMachoLink(ctxt *Link) int64 {
1128 machosymtab(ctxt)
1129 machoDyldInfo(ctxt)
1130
1131 ldr := ctxt.loader
1132
1133
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
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
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
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
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
1214
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
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
1276
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
1287 return nil, nil
1288 }
1289 return peekMachoPlatform(m)
1290 }
1291
1292
1293
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
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
1331
1332
1333
1334
1335
1336
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
1349
1350
1351
1352
1353
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
1366
1367
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
1400 }
1401
1402
1403
1404
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
1420
1421
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 {
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
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)
1450 bind.Grow(sz)
1451 bind.SetSize(sz)
1452
1453
1454
1455
1456
1457
1458
1459 }
1460
1461
1462
1463
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
1477
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
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
1520
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
1530
1531 return fmt.Errorf("unexpected content after code signature")
1532 }
1533
1534 sz := codesign.Size(sigOff, "a.out")
1535 if sz != sigSz {
1536
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
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 }
1566
View as plain text