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