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
484
485
486 version = 10<<16 | 13<<8 | 0<<0
487 case sys.ARM64:
488 version = 11<<16 | 0<<8 | 0<<0
489 }
490 ml := newMachoLoad(ctxt.Arch, LC_BUILD_VERSION, 4)
491 ml.data[0] = uint32(machoPlatform)
492 ml.data[1] = version
493 ml.data[2] = version
494 ml.data[3] = 0
495 }
496 }
497
498
499 s := ctxt.loader.LookupOrCreateSym(".machosymstr", 0)
500 sb := ctxt.loader.MakeSymbolUpdater(s)
501
502 sb.SetType(sym.SMACHOSYMSTR)
503 sb.SetReachable(true)
504 sb.AddUint8(' ')
505 sb.AddUint8('\x00')
506
507 s = ctxt.loader.LookupOrCreateSym(".machosymtab", 0)
508 sb = ctxt.loader.MakeSymbolUpdater(s)
509 sb.SetType(sym.SMACHOSYMTAB)
510 sb.SetReachable(true)
511
512 if ctxt.IsInternal() {
513 s = ctxt.loader.LookupOrCreateSym(".plt", 0)
514 sb = ctxt.loader.MakeSymbolUpdater(s)
515 sb.SetType(sym.SMACHOPLT)
516 sb.SetReachable(true)
517
518 s = ctxt.loader.LookupOrCreateSym(".got", 0)
519 sb = ctxt.loader.MakeSymbolUpdater(s)
520 sb.SetType(sym.SMACHOGOT)
521 sb.SetReachable(true)
522 sb.SetAlign(4)
523
524 s = ctxt.loader.LookupOrCreateSym(".linkedit.plt", 0)
525 sb = ctxt.loader.MakeSymbolUpdater(s)
526 sb.SetType(sym.SMACHOINDIRECTPLT)
527 sb.SetReachable(true)
528
529 s = ctxt.loader.LookupOrCreateSym(".linkedit.got", 0)
530 sb = ctxt.loader.MakeSymbolUpdater(s)
531 sb.SetType(sym.SMACHOINDIRECTGOT)
532 sb.SetReachable(true)
533 }
534
535
536 if ctxt.IsExternal() {
537 s = ctxt.loader.LookupOrCreateSym(".llvmasm", 0)
538 sb = ctxt.loader.MakeSymbolUpdater(s)
539 sb.SetType(sym.SMACHO)
540 sb.SetReachable(true)
541 sb.AddUint8(0)
542 }
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559 if ctxt.BuildMode == BuildModePlugin {
560 for _, name := range []string{"_cgo_topofstack", "__cgo_topofstack", "_cgo_panic", "crosscall2"} {
561
562
563 ver := 0
564
565 if name == "_cgo_panic" {
566 ver = abiInternalVer
567 }
568 s := ctxt.loader.Lookup(name, ver)
569 if s != 0 {
570 ctxt.loader.SetAttrCgoExportDynamic(s, false)
571 }
572 }
573 }
574 }
575
576 func machoadddynlib(lib string, linkmode LinkMode) {
577 if seenlib[lib] || linkmode == LinkExternal {
578 return
579 }
580 seenlib[lib] = true
581
582
583
584
585
586 loadBudget -= (len(lib)+7)/8*8 + 24
587
588 if loadBudget < 0 {
589 HEADR += 4096
590 *FlagTextAddr += 4096
591 loadBudget += 4096
592 }
593
594 dylib = append(dylib, lib)
595 }
596
597 func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) {
598 buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
599
600 msect := newMachoSect(mseg, buf, segname)
601
602 if sect.Rellen > 0 {
603 msect.reloc = uint32(sect.Reloff)
604 msect.nreloc = uint32(sect.Rellen / 8)
605 }
606
607 for 1<<msect.align < sect.Align {
608 msect.align++
609 }
610 msect.addr = sect.Vaddr
611 msect.size = sect.Length
612
613 if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
614
615 if sect.Length > sect.Seg.Vaddr+sect.Seg.Filelen-sect.Vaddr {
616 Errorf(nil, "macho cannot represent section %s crossing data and bss", sect.Name)
617 }
618 msect.off = uint32(sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr)
619 } else {
620 msect.off = 0
621 msect.flag |= S_ZEROFILL
622 }
623
624 if sect.Rwx&1 != 0 {
625 msect.flag |= S_ATTR_SOME_INSTRUCTIONS
626 }
627
628 if sect.Name == ".text" {
629 msect.flag |= S_ATTR_PURE_INSTRUCTIONS
630 }
631
632 if sect.Name == ".plt" {
633 msect.name = "__symbol_stub1"
634 msect.flag = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS | S_SYMBOL_STUBS
635 msect.res1 = 0
636 msect.res2 = 6
637 }
638
639 if sect.Name == ".got" {
640 msect.name = "__nl_symbol_ptr"
641 msect.flag = S_NON_LAZY_SYMBOL_POINTERS
642 msect.res1 = uint32(ctxt.loader.SymSize(ctxt.ArchSyms.LinkEditPLT) / 4)
643 }
644
645 if sect.Name == ".init_array" {
646 msect.name = "__mod_init_func"
647 msect.flag = S_MOD_INIT_FUNC_POINTERS
648 }
649
650
651
652
653
654
655
656 if sect.Name == ".llvmasm" {
657 msect.name = "__asm"
658 msect.segname = "__LLVM"
659 }
660
661 if segname == "__DWARF" {
662 msect.flag |= S_ATTR_DEBUG
663 }
664 }
665
666 func asmbMacho(ctxt *Link) {
667 machlink := doMachoLink(ctxt)
668 if ctxt.IsExternal() {
669 symo := int64(Segdwarf.Fileoff + uint64(Rnd(int64(Segdwarf.Filelen), *FlagRound)) + uint64(machlink))
670 ctxt.Out.SeekSet(symo)
671 machoEmitReloc(ctxt)
672 }
673 ctxt.Out.SeekSet(0)
674
675 ldr := ctxt.loader
676
677
678 va := *FlagTextAddr - int64(HEADR)
679
680 mh := getMachoHdr()
681 switch ctxt.Arch.Family {
682 default:
683 Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
684
685 case sys.AMD64:
686 mh.cpu = MACHO_CPU_AMD64
687 mh.subcpu = MACHO_SUBCPU_X86
688
689 case sys.ARM64:
690 mh.cpu = MACHO_CPU_ARM64
691 mh.subcpu = MACHO_SUBCPU_ARM64_ALL
692 }
693
694 var ms *MachoSeg
695 if ctxt.LinkMode == LinkExternal {
696
697 ms = newMachoSeg("", 40)
698
699 ms.fileoffset = Segtext.Fileoff
700 ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
701 ms.vsize = Segdwarf.Vaddr + Segdwarf.Length - Segtext.Vaddr
702 }
703
704
705 if ctxt.LinkMode != LinkExternal {
706 ms = newMachoSeg("__PAGEZERO", 0)
707 ms.vsize = uint64(va)
708 }
709
710
711 v := Rnd(int64(uint64(HEADR)+Segtext.Length), *FlagRound)
712
713 var mstext *MachoSeg
714 if ctxt.LinkMode != LinkExternal {
715 ms = newMachoSeg("__TEXT", 20)
716 ms.vaddr = uint64(va)
717 ms.vsize = uint64(v)
718 ms.fileoffset = 0
719 ms.filesize = uint64(v)
720 ms.prot1 = 7
721 ms.prot2 = 5
722 mstext = ms
723 }
724
725 for _, sect := range Segtext.Sections {
726 machoshbits(ctxt, ms, sect, "__TEXT")
727 }
728
729
730 if ctxt.LinkMode != LinkExternal && Segrelrodata.Length > 0 {
731 ms = newMachoSeg("__DATA_CONST", 20)
732 ms.vaddr = Segrelrodata.Vaddr
733 ms.vsize = Segrelrodata.Length
734 ms.fileoffset = Segrelrodata.Fileoff
735 ms.filesize = Segrelrodata.Filelen
736 ms.prot1 = 3
737 ms.prot2 = 3
738 ms.flag = 0x10
739 }
740
741 for _, sect := range Segrelrodata.Sections {
742 machoshbits(ctxt, ms, sect, "__DATA_CONST")
743 }
744
745
746 if ctxt.LinkMode != LinkExternal {
747 ms = newMachoSeg("__DATA", 20)
748 ms.vaddr = Segdata.Vaddr
749 ms.vsize = Segdata.Length
750 ms.fileoffset = Segdata.Fileoff
751 ms.filesize = Segdata.Filelen
752 ms.prot1 = 3
753 ms.prot2 = 3
754 }
755
756 for _, sect := range Segdata.Sections {
757 machoshbits(ctxt, ms, sect, "__DATA")
758 }
759
760
761 if !*FlagW {
762 if ctxt.LinkMode != LinkExternal {
763 ms = newMachoSeg("__DWARF", 20)
764 ms.vaddr = Segdwarf.Vaddr
765 ms.vsize = 0
766 ms.fileoffset = Segdwarf.Fileoff
767 ms.filesize = Segdwarf.Filelen
768 }
769 for _, sect := range Segdwarf.Sections {
770 machoshbits(ctxt, ms, sect, "__DWARF")
771 }
772 }
773
774 if ctxt.LinkMode != LinkExternal {
775 switch ctxt.Arch.Family {
776 default:
777 Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
778
779 case sys.AMD64:
780 ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 42+2)
781 ml.data[0] = 4
782 ml.data[1] = 42
783 ml.data[2+32] = uint32(Entryvalue(ctxt))
784 ml.data[2+32+1] = uint32(Entryvalue(ctxt) >> 32)
785
786 case sys.ARM64:
787 ml := newMachoLoad(ctxt.Arch, LC_MAIN, 4)
788 ml.data[0] = uint32(uint64(Entryvalue(ctxt)) - (Segtext.Vaddr - uint64(HEADR)))
789 ml.data[1] = uint32((uint64(Entryvalue(ctxt)) - (Segtext.Vaddr - uint64(HEADR))) >> 32)
790 }
791 }
792
793 var codesigOff int64
794 if !*FlagD {
795
796 s1 := ldr.SymSize(ldr.Lookup(".machorebase", 0))
797 s2 := ldr.SymSize(ldr.Lookup(".machobind", 0))
798 s3 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
799 s4 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
800 s5 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
801 s6 := ldr.SymSize(ldr.Lookup(".machosymstr", 0))
802 s7 := ldr.SymSize(ldr.Lookup(".machocodesig", 0))
803
804 if ctxt.LinkMode != LinkExternal {
805 ms := newMachoSeg("__LINKEDIT", 0)
806 ms.vaddr = uint64(Rnd(int64(Segdata.Vaddr+Segdata.Length), *FlagRound))
807 ms.vsize = uint64(s1 + s2 + s3 + s4 + s5 + s6 + s7)
808 ms.fileoffset = uint64(linkoff)
809 ms.filesize = ms.vsize
810 ms.prot1 = 1
811 ms.prot2 = 1
812
813 codesigOff = linkoff + s1 + s2 + s3 + s4 + s5 + s6
814 }
815
816 if ctxt.LinkMode != LinkExternal && ctxt.IsPIE() {
817 ml := newMachoLoad(ctxt.Arch, LC_DYLD_INFO_ONLY, 10)
818 ml.data[0] = uint32(linkoff)
819 ml.data[1] = uint32(s1)
820 ml.data[2] = uint32(linkoff + s1)
821 ml.data[3] = uint32(s2)
822 ml.data[4] = 0
823 ml.data[5] = 0
824 ml.data[6] = 0
825 ml.data[7] = 0
826 ml.data[8] = 0
827 ml.data[9] = 0
828 }
829
830 ml := newMachoLoad(ctxt.Arch, LC_SYMTAB, 4)
831 ml.data[0] = uint32(linkoff + s1 + s2)
832 ml.data[1] = uint32(nsortsym)
833 ml.data[2] = uint32(linkoff + s1 + s2 + s3 + s4 + s5)
834 ml.data[3] = uint32(s6)
835
836 if ctxt.LinkMode != LinkExternal {
837 machodysymtab(ctxt, linkoff+s1+s2)
838
839 ml := newMachoLoad(ctxt.Arch, LC_LOAD_DYLINKER, 6)
840 ml.data[0] = 12
841 stringtouint32(ml.data[1:], "/usr/lib/dyld")
842
843 for _, lib := range dylib {
844 ml = newMachoLoad(ctxt.Arch, LC_LOAD_DYLIB, 4+(uint32(len(lib))+1+7)/8*2)
845 ml.data[0] = 24
846 ml.data[1] = 0
847 ml.data[2] = 0
848 ml.data[3] = 0
849 stringtouint32(ml.data[4:], lib)
850 }
851 }
852
853 if ctxt.IsInternal() && ctxt.NeedCodeSign() {
854 ml := newMachoLoad(ctxt.Arch, LC_CODE_SIGNATURE, 2)
855 ml.data[0] = uint32(codesigOff)
856 ml.data[1] = uint32(s7)
857 }
858 }
859
860 a := machowrite(ctxt, ctxt.Arch, ctxt.Out, ctxt.LinkMode)
861 if int32(a) > HEADR {
862 Exitf("HEADR too small: %d > %d", a, HEADR)
863 }
864
865
866
867 if ctxt.IsInternal() && ctxt.NeedCodeSign() {
868 cs := ldr.Lookup(".machocodesig", 0)
869 data := ctxt.Out.Data()
870 if int64(len(data)) != codesigOff {
871 panic("wrong size")
872 }
873 codesign.Sign(ldr.Data(cs), bytes.NewReader(data), "a.out", codesigOff, int64(mstext.fileoffset), int64(mstext.filesize), ctxt.IsExe() || ctxt.IsPIE())
874 ctxt.Out.SeekSet(codesigOff)
875 ctxt.Out.Write(ldr.Data(cs))
876 }
877 }
878
879 func symkind(ldr *loader.Loader, s loader.Sym) int {
880 if t := ldr.SymType(s); t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {
881 return SymKindUndef
882 }
883 if ldr.AttrCgoExport(s) {
884 return SymKindExtdef
885 }
886 return SymKindLocal
887 }
888
889 func collectmachosyms(ctxt *Link) {
890 ldr := ctxt.loader
891
892 addsym := func(s loader.Sym) {
893 sortsym = append(sortsym, s)
894 nkind[symkind(ldr, s)]++
895 }
896
897
898
899
900
901
902
903
904
905
906 if !*FlagS {
907 if !ctxt.DynlinkingGo() {
908 s := ldr.Lookup("runtime.text", 0)
909 if ldr.SymType(s) == sym.STEXT {
910 addsym(s)
911 }
912 }
913 for n := range Segtext.Sections[1:] {
914 s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0)
915 if s != 0 {
916 addsym(s)
917 } else {
918 break
919 }
920 }
921 if !ctxt.DynlinkingGo() {
922 s := ldr.Lookup("runtime.etext", 0)
923 if ldr.SymType(s) == sym.STEXT {
924 addsym(s)
925 }
926 }
927 }
928
929
930 for _, s := range ctxt.Textp {
931 if *FlagS && !ldr.AttrCgoExportDynamic(s) {
932 continue
933 }
934 addsym(s)
935 }
936
937 shouldBeInSymbolTable := func(s loader.Sym) bool {
938 if ldr.AttrNotInSymbolTable(s) {
939 return false
940 }
941 name := ldr.SymName(s)
942 if name == "" || name[0] == '.' {
943 return false
944 }
945 return true
946 }
947
948
949 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
950 if !ldr.AttrReachable(s) {
951 continue
952 }
953 t := ldr.SymType(s)
954 if t >= sym.SELFRXSECT && t < sym.SXREF {
955 if t == sym.STLSBSS {
956
957 continue
958 }
959 if !shouldBeInSymbolTable(s) {
960 continue
961 }
962 if *FlagS && !ldr.AttrCgoExportDynamic(s) {
963 continue
964 }
965 addsym(s)
966 continue
967 }
968
969 switch t {
970 case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
971
972 addsym(s)
973 }
974
975
976 if t == sym.SDYNIMPORT && ldr.SymDynimplib(s) == "/usr/lib/libSystem.B.dylib" {
977
978 if machoPlatform == PLATFORM_MACOS {
979 switch n := ldr.SymExtname(s); n {
980 case "fdopendir":
981 switch buildcfg.GOARCH {
982 case "amd64":
983 ldr.SetSymExtname(s, n+"$INODE64")
984 }
985 case "readdir_r", "getfsstat":
986 switch buildcfg.GOARCH {
987 case "amd64":
988 ldr.SetSymExtname(s, n+"$INODE64")
989 }
990 }
991 }
992 }
993 }
994
995 nsortsym = len(sortsym)
996 }
997
998 func machosymorder(ctxt *Link) {
999 ldr := ctxt.loader
1000
1001
1002
1003
1004 for _, s := range ctxt.dynexp {
1005 if !ldr.AttrReachable(s) {
1006 panic("dynexp symbol is not reachable")
1007 }
1008 }
1009 collectmachosyms(ctxt)
1010 sort.Slice(sortsym[:nsortsym], func(i, j int) bool {
1011 s1 := sortsym[i]
1012 s2 := sortsym[j]
1013 k1 := symkind(ldr, s1)
1014 k2 := symkind(ldr, s2)
1015 if k1 != k2 {
1016 return k1 < k2
1017 }
1018 return ldr.SymExtname(s1) < ldr.SymExtname(s2)
1019 })
1020 for i, s := range sortsym {
1021 ldr.SetSymDynid(s, int32(i))
1022 }
1023 }
1024
1025
1026
1027 func AddMachoSym(ldr *loader.Loader, s loader.Sym) {
1028 ldr.SetSymDynid(s, int32(nsortsym))
1029 sortsym = append(sortsym, s)
1030 nsortsym++
1031 nkind[symkind(ldr, s)]++
1032 }
1033
1034
1035
1036
1037
1038 func machoShouldExport(ctxt *Link, ldr *loader.Loader, s loader.Sym) bool {
1039 if !ctxt.DynlinkingGo() || ldr.AttrLocal(s) {
1040 return false
1041 }
1042 if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(ldr.SymExtname(s), objabi.PathToPrefix(*flagPluginPath)) {
1043 return true
1044 }
1045 name := ldr.SymName(s)
1046 if strings.HasPrefix(name, "go:itab.") {
1047 return true
1048 }
1049 if strings.HasPrefix(name, "type:") && !strings.HasPrefix(name, "type:.") {
1050
1051
1052
1053 return true
1054 }
1055 if strings.HasPrefix(name, "go:link.pkghash") {
1056 return true
1057 }
1058 return ldr.SymType(s) >= sym.SFirstWritable
1059 }
1060
1061 func machosymtab(ctxt *Link) {
1062 ldr := ctxt.loader
1063 symtab := ldr.CreateSymForUpdate(".machosymtab", 0)
1064 symstr := ldr.CreateSymForUpdate(".machosymstr", 0)
1065
1066 for _, s := range sortsym[:nsortsym] {
1067 symtab.AddUint32(ctxt.Arch, uint32(symstr.Size()))
1068
1069 export := machoShouldExport(ctxt, ldr, s)
1070
1071
1072
1073
1074
1075 symstr.AddUint8('_')
1076
1077
1078 name := strings.Replace(ldr.SymExtname(s), "·", ".", -1)
1079
1080 name = mangleABIName(ctxt, ldr, s, name)
1081 symstr.Addstring(name)
1082
1083 if t := ldr.SymType(s); t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {
1084 symtab.AddUint8(0x01)
1085 symtab.AddUint8(0)
1086 symtab.AddUint16(ctxt.Arch, 0)
1087 symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize)
1088 } else {
1089 if export || ldr.AttrCgoExportDynamic(s) {
1090 symtab.AddUint8(0x0f)
1091 } else if ldr.AttrCgoExportStatic(s) {
1092
1093 symtab.AddUint8(0x1f)
1094 } else {
1095 symtab.AddUint8(0x0e)
1096 }
1097 o := s
1098 if outer := ldr.OuterSym(o); outer != 0 {
1099 o = outer
1100 }
1101 if ldr.SymSect(o) == nil {
1102 ldr.Errorf(s, "missing section for symbol")
1103 symtab.AddUint8(0)
1104 } else {
1105 symtab.AddUint8(uint8(ldr.SymSect(o).Extnum))
1106 }
1107 symtab.AddUint16(ctxt.Arch, 0)
1108 symtab.AddUintXX(ctxt.Arch, uint64(ldr.SymAddr(s)), ctxt.Arch.PtrSize)
1109 }
1110 }
1111 }
1112
1113 func machodysymtab(ctxt *Link, base int64) {
1114 ml := newMachoLoad(ctxt.Arch, LC_DYSYMTAB, 18)
1115
1116 n := 0
1117 ml.data[0] = uint32(n)
1118 ml.data[1] = uint32(nkind[SymKindLocal])
1119 n += nkind[SymKindLocal]
1120
1121 ml.data[2] = uint32(n)
1122 ml.data[3] = uint32(nkind[SymKindExtdef])
1123 n += nkind[SymKindExtdef]
1124
1125 ml.data[4] = uint32(n)
1126 ml.data[5] = uint32(nkind[SymKindUndef])
1127
1128 ml.data[6] = 0
1129 ml.data[7] = 0
1130 ml.data[8] = 0
1131 ml.data[9] = 0
1132 ml.data[10] = 0
1133 ml.data[11] = 0
1134
1135 ldr := ctxt.loader
1136
1137
1138 s1 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
1139 s2 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
1140 s3 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
1141 ml.data[12] = uint32(base + s1)
1142 ml.data[13] = uint32((s2 + s3) / 4)
1143
1144 ml.data[14] = 0
1145 ml.data[15] = 0
1146 ml.data[16] = 0
1147 ml.data[17] = 0
1148 }
1149
1150 func doMachoLink(ctxt *Link) int64 {
1151 machosymtab(ctxt)
1152 machoDyldInfo(ctxt)
1153
1154 ldr := ctxt.loader
1155
1156
1157 s1 := ldr.Lookup(".machorebase", 0)
1158 s2 := ldr.Lookup(".machobind", 0)
1159 s3 := ldr.Lookup(".machosymtab", 0)
1160 s4 := ctxt.ArchSyms.LinkEditPLT
1161 s5 := ctxt.ArchSyms.LinkEditGOT
1162 s6 := ldr.Lookup(".machosymstr", 0)
1163
1164 size := ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4) + ldr.SymSize(s5) + ldr.SymSize(s6)
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183 if size%16 != 0 {
1184 n := 16 - size%16
1185 s6b := ldr.MakeSymbolUpdater(s6)
1186 s6b.Grow(s6b.Size() + n)
1187 s6b.SetSize(s6b.Size() + n)
1188 size += n
1189 }
1190
1191 if size > 0 {
1192 linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), *FlagRound) + Rnd(int64(Segrelrodata.Filelen), *FlagRound) + Rnd(int64(Segdata.Filelen), *FlagRound) + Rnd(int64(Segdwarf.Filelen), *FlagRound)
1193 ctxt.Out.SeekSet(linkoff)
1194
1195 ctxt.Out.Write(ldr.Data(s1))
1196 ctxt.Out.Write(ldr.Data(s2))
1197 ctxt.Out.Write(ldr.Data(s3))
1198 ctxt.Out.Write(ldr.Data(s4))
1199 ctxt.Out.Write(ldr.Data(s5))
1200 ctxt.Out.Write(ldr.Data(s6))
1201
1202
1203 s7 := machoCodeSigSym(ctxt, linkoff+size)
1204 size += ldr.SymSize(s7)
1205 }
1206
1207 return Rnd(size, *FlagRound)
1208 }
1209
1210 func machorelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
1211
1212 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1213 return
1214 }
1215 ldr := ctxt.loader
1216
1217 for i, s := range syms {
1218 if !ldr.AttrReachable(s) {
1219 continue
1220 }
1221 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1222 syms = syms[i:]
1223 break
1224 }
1225 }
1226
1227 eaddr := sect.Vaddr + sect.Length
1228 for _, s := range syms {
1229 if !ldr.AttrReachable(s) {
1230 continue
1231 }
1232 if ldr.SymValue(s) >= int64(eaddr) {
1233 break
1234 }
1235
1236
1237
1238 relocs := ldr.Relocs(s)
1239 for ri := 0; ri < relocs.Count(); ri++ {
1240 r := relocs.At(ri)
1241 rr, ok := extreloc(ctxt, ldr, s, r)
1242 if !ok {
1243 continue
1244 }
1245 if rr.Xsym == 0 {
1246 ldr.Errorf(s, "missing xsym in relocation")
1247 continue
1248 }
1249 if !ldr.AttrReachable(rr.Xsym) {
1250 ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
1251 }
1252 if !thearch.Machoreloc1(ctxt.Arch, out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
1253 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()))
1254 }
1255 }
1256 }
1257
1258
1259 if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
1260 panic("machorelocsect: size mismatch")
1261 }
1262 }
1263
1264 func machoEmitReloc(ctxt *Link) {
1265 for ctxt.Out.Offset()&7 != 0 {
1266 ctxt.Out.Write8(0)
1267 }
1268
1269 sizeExtRelocs(ctxt, thearch.MachorelocSize)
1270 relocSect, wg := relocSectFn(ctxt, machorelocsect)
1271
1272 relocSect(ctxt, Segtext.Sections[0], ctxt.Textp)
1273 for _, sect := range Segtext.Sections[1:] {
1274 if sect.Name == ".text" {
1275 relocSect(ctxt, sect, ctxt.Textp)
1276 } else {
1277 relocSect(ctxt, sect, ctxt.datap)
1278 }
1279 }
1280 for _, sect := range Segrelrodata.Sections {
1281 relocSect(ctxt, sect, ctxt.datap)
1282 }
1283 for _, sect := range Segdata.Sections {
1284 relocSect(ctxt, sect, ctxt.datap)
1285 }
1286 for i := 0; i < len(Segdwarf.Sections); i++ {
1287 sect := Segdwarf.Sections[i]
1288 si := dwarfp[i]
1289 if si.secSym() != loader.Sym(sect.Sym) ||
1290 ctxt.loader.SymSect(si.secSym()) != sect {
1291 panic("inconsistency between dwarfp and Segdwarf")
1292 }
1293 relocSect(ctxt, sect, si.syms)
1294 }
1295 wg.Wait()
1296 }
1297
1298
1299
1300 func hostobjMachoPlatform(h *Hostobj) (*MachoPlatformLoad, error) {
1301 f, err := os.Open(h.file)
1302 if err != nil {
1303 return nil, fmt.Errorf("%s: failed to open host object: %v\n", h.file, err)
1304 }
1305 defer f.Close()
1306 sr := io.NewSectionReader(f, h.off, h.length)
1307 m, err := macho.NewFile(sr)
1308 if err != nil {
1309
1310 return nil, nil
1311 }
1312 return peekMachoPlatform(m)
1313 }
1314
1315
1316
1317 func peekMachoPlatform(m *macho.File) (*MachoPlatformLoad, error) {
1318 for _, cmd := range m.Loads {
1319 raw := cmd.Raw()
1320 ml := MachoLoad{
1321 type_: m.ByteOrder.Uint32(raw),
1322 }
1323
1324 data := raw[8:]
1325 var p MachoPlatform
1326 switch ml.type_ {
1327 case LC_VERSION_MIN_IPHONEOS:
1328 p = PLATFORM_IOS
1329 case LC_VERSION_MIN_MACOSX:
1330 p = PLATFORM_MACOS
1331 case LC_VERSION_MIN_WATCHOS:
1332 p = PLATFORM_WATCHOS
1333 case LC_VERSION_MIN_TVOS:
1334 p = PLATFORM_TVOS
1335 case LC_BUILD_VERSION:
1336 p = MachoPlatform(m.ByteOrder.Uint32(data))
1337 default:
1338 continue
1339 }
1340 ml.data = make([]uint32, len(data)/4)
1341 r := bytes.NewReader(data)
1342 if err := binary.Read(r, m.ByteOrder, &ml.data); err != nil {
1343 return nil, err
1344 }
1345 return &MachoPlatformLoad{
1346 platform: p,
1347 cmd: ml,
1348 }, nil
1349 }
1350 return nil, nil
1351 }
1352
1353
1354
1355
1356
1357
1358
1359
1360 type machoRebaseRecord struct {
1361 sym loader.Sym
1362 off int64
1363 }
1364
1365 var machorebase []machoRebaseRecord
1366
1367 func MachoAddRebase(s loader.Sym, off int64) {
1368 machorebase = append(machorebase, machoRebaseRecord{s, off})
1369 }
1370
1371
1372
1373
1374
1375
1376
1377 type machoBindRecord struct {
1378 off int64
1379 targ loader.Sym
1380 }
1381
1382 var machobind []machoBindRecord
1383
1384 func MachoAddBind(off int64, targ loader.Sym) {
1385 machobind = append(machobind, machoBindRecord{off, targ})
1386 }
1387
1388
1389
1390
1391 func machoDyldInfo(ctxt *Link) {
1392 ldr := ctxt.loader
1393 rebase := ldr.CreateSymForUpdate(".machorebase", 0)
1394 bind := ldr.CreateSymForUpdate(".machobind", 0)
1395
1396 if !(ctxt.IsPIE() && ctxt.IsInternal()) {
1397 return
1398 }
1399
1400 segId := func(seg *sym.Segment) uint8 {
1401 switch seg {
1402 case &Segtext:
1403 return 1
1404 case &Segrelrodata:
1405 return 2
1406 case &Segdata:
1407 if Segrelrodata.Length > 0 {
1408 return 3
1409 }
1410 return 2
1411 }
1412 panic("unknown segment")
1413 }
1414
1415 dylibId := func(s loader.Sym) int {
1416 slib := ldr.SymDynimplib(s)
1417 for i, lib := range dylib {
1418 if lib == slib {
1419 return i + 1
1420 }
1421 }
1422 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP
1423 }
1424
1425
1426
1427
1428 rebase.AddUint8(REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER)
1429 for _, r := range machorebase {
1430 seg := ldr.SymSect(r.sym).Seg
1431 off := uint64(ldr.SymValue(r.sym)+r.off) - seg.Vaddr
1432 rebase.AddUint8(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segId(seg))
1433 rebase.AddUleb(off)
1434
1435 rebase.AddUint8(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1)
1436 }
1437 rebase.AddUint8(REBASE_OPCODE_DONE)
1438 sz := Rnd(rebase.Size(), 8)
1439 rebase.Grow(sz)
1440 rebase.SetSize(sz)
1441
1442
1443
1444
1445 got := ctxt.GOT
1446 seg := ldr.SymSect(got).Seg
1447 gotAddr := ldr.SymValue(got)
1448 bind.AddUint8(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER)
1449 for _, r := range machobind {
1450 off := uint64(gotAddr+r.off) - seg.Vaddr
1451 bind.AddUint8(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segId(seg))
1452 bind.AddUleb(off)
1453
1454 d := dylibId(r.targ)
1455 if d > 0 && d < 128 {
1456 bind.AddUint8(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | uint8(d)&0xf)
1457 } else if d >= 128 {
1458 bind.AddUint8(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB)
1459 bind.AddUleb(uint64(d))
1460 } else {
1461 bind.AddUint8(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | uint8(d)&0xf)
1462 }
1463
1464 bind.AddUint8(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
1465
1466 bind.AddUint8('_')
1467 bind.Addstring(ldr.SymExtname(r.targ))
1468
1469 bind.AddUint8(BIND_OPCODE_DO_BIND)
1470 }
1471 bind.AddUint8(BIND_OPCODE_DONE)
1472 sz = Rnd(bind.Size(), 16)
1473 bind.Grow(sz)
1474 bind.SetSize(sz)
1475
1476
1477
1478
1479
1480
1481
1482 }
1483
1484
1485
1486
1487 func machoCodeSigSym(ctxt *Link, codeSize int64) loader.Sym {
1488 ldr := ctxt.loader
1489 cs := ldr.CreateSymForUpdate(".machocodesig", 0)
1490 if !ctxt.NeedCodeSign() || ctxt.IsExternal() {
1491 return cs.Sym()
1492 }
1493 sz := codesign.Size(codeSize, "a.out")
1494 cs.Grow(sz)
1495 cs.SetSize(sz)
1496 return cs.Sym()
1497 }
1498
1499
1500
1501 func machoCodeSign(ctxt *Link, fname string) error {
1502 f, err := os.OpenFile(fname, os.O_RDWR, 0)
1503 if err != nil {
1504 return err
1505 }
1506 defer f.Close()
1507
1508 mf, err := macho.NewFile(f)
1509 if err != nil {
1510 return err
1511 }
1512 if mf.Magic != macho.Magic64 {
1513 Exitf("not 64-bit Mach-O file: %s", fname)
1514 }
1515
1516
1517 var sigOff, sigSz, csCmdOff, linkeditOff int64
1518 var linkeditSeg, textSeg *macho.Segment
1519 loadOff := int64(machoHeaderSize64)
1520 get32 := mf.ByteOrder.Uint32
1521 for _, l := range mf.Loads {
1522 data := l.Raw()
1523 cmd, sz := get32(data), get32(data[4:])
1524 if cmd == LC_CODE_SIGNATURE {
1525 sigOff = int64(get32(data[8:]))
1526 sigSz = int64(get32(data[12:]))
1527 csCmdOff = loadOff
1528 }
1529 if seg, ok := l.(*macho.Segment); ok {
1530 switch seg.Name {
1531 case "__LINKEDIT":
1532 linkeditSeg = seg
1533 linkeditOff = loadOff
1534 case "__TEXT":
1535 textSeg = seg
1536 }
1537 }
1538 loadOff += int64(sz)
1539 }
1540
1541 if sigOff == 0 {
1542
1543
1544 return nil
1545 }
1546
1547 fi, err := f.Stat()
1548 if err != nil {
1549 return err
1550 }
1551 if sigOff+sigSz != fi.Size() {
1552
1553
1554 return fmt.Errorf("unexpected content after code signature")
1555 }
1556
1557 sz := codesign.Size(sigOff, "a.out")
1558 if sz != sigSz {
1559
1560 var tmp [8]byte
1561 mf.ByteOrder.PutUint32(tmp[:4], uint32(sz))
1562 _, err = f.WriteAt(tmp[:4], csCmdOff+12)
1563 if err != nil {
1564 return err
1565 }
1566
1567
1568 segSz := sigOff + sz - int64(linkeditSeg.Offset)
1569 mf.ByteOrder.PutUint64(tmp[:8], uint64(segSz))
1570 _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Memsz)))
1571 if err != nil {
1572 return err
1573 }
1574 _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Filesz)))
1575 if err != nil {
1576 return err
1577 }
1578 }
1579
1580 cs := make([]byte, sz)
1581 codesign.Sign(cs, f, "a.out", sigOff, int64(textSeg.Offset), int64(textSeg.Filesz), ctxt.IsExe() || ctxt.IsPIE())
1582 _, err = f.WriteAt(cs, sigOff)
1583 if err != nil {
1584 return err
1585 }
1586 err = f.Truncate(sigOff + sz)
1587 return err
1588 }
1589
View as plain text