Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/link/internal/ld/macho.go

Documentation: cmd/link/internal/ld

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

View as plain text