github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/ld/macho.go (about)

     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  	"github.com/gagliardetto/golang-go/cmd/internal/objabi"
    10  	"github.com/gagliardetto/golang-go/cmd/internal/sys"
    11  	"github.com/gagliardetto/golang-go/cmd/link/internal/sym"
    12  	"debug/macho"
    13  	"encoding/binary"
    14  	"fmt"
    15  	"io"
    16  	"os"
    17  	"sort"
    18  	"strings"
    19  )
    20  
    21  type MachoHdr struct {
    22  	cpu    uint32
    23  	subcpu uint32
    24  }
    25  
    26  type MachoSect struct {
    27  	name    string
    28  	segname string
    29  	addr    uint64
    30  	size    uint64
    31  	off     uint32
    32  	align   uint32
    33  	reloc   uint32
    34  	nreloc  uint32
    35  	flag    uint32
    36  	res1    uint32
    37  	res2    uint32
    38  }
    39  
    40  type MachoSeg struct {
    41  	name       string
    42  	vsize      uint64
    43  	vaddr      uint64
    44  	fileoffset uint64
    45  	filesize   uint64
    46  	prot1      uint32
    47  	prot2      uint32
    48  	nsect      uint32
    49  	msect      uint32
    50  	sect       []MachoSect
    51  	flag       uint32
    52  }
    53  
    54  // MachoPlatformLoad represents a LC_VERSION_MIN_* or
    55  // LC_BUILD_VERSION load command.
    56  type MachoPlatformLoad struct {
    57  	platform MachoPlatform // One of PLATFORM_* constants.
    58  	cmd      MachoLoad
    59  }
    60  
    61  type MachoLoad struct {
    62  	type_ uint32
    63  	data  []uint32
    64  }
    65  
    66  type MachoPlatform int
    67  
    68  /*
    69   * Total amount of space to reserve at the start of the file
    70   * for Header, PHeaders, and SHeaders.
    71   * May waste some.
    72   */
    73  const (
    74  	INITIAL_MACHO_HEADR = 4 * 1024
    75  )
    76  
    77  const (
    78  	MACHO_CPU_AMD64               = 1<<24 | 7
    79  	MACHO_CPU_386                 = 7
    80  	MACHO_SUBCPU_X86              = 3
    81  	MACHO_CPU_ARM                 = 12
    82  	MACHO_SUBCPU_ARM              = 0
    83  	MACHO_SUBCPU_ARMV7            = 9
    84  	MACHO_CPU_ARM64               = 1<<24 | 12
    85  	MACHO_SUBCPU_ARM64_ALL        = 0
    86  	MACHO32SYMSIZE                = 12
    87  	MACHO64SYMSIZE                = 16
    88  	MACHO_X86_64_RELOC_UNSIGNED   = 0
    89  	MACHO_X86_64_RELOC_SIGNED     = 1
    90  	MACHO_X86_64_RELOC_BRANCH     = 2
    91  	MACHO_X86_64_RELOC_GOT_LOAD   = 3
    92  	MACHO_X86_64_RELOC_GOT        = 4
    93  	MACHO_X86_64_RELOC_SUBTRACTOR = 5
    94  	MACHO_X86_64_RELOC_SIGNED_1   = 6
    95  	MACHO_X86_64_RELOC_SIGNED_2   = 7
    96  	MACHO_X86_64_RELOC_SIGNED_4   = 8
    97  	MACHO_ARM_RELOC_VANILLA       = 0
    98  	MACHO_ARM_RELOC_PAIR          = 1
    99  	MACHO_ARM_RELOC_SECTDIFF      = 2
   100  	MACHO_ARM_RELOC_BR24          = 5
   101  	MACHO_ARM64_RELOC_UNSIGNED    = 0
   102  	MACHO_ARM64_RELOC_BRANCH26    = 2
   103  	MACHO_ARM64_RELOC_PAGE21      = 3
   104  	MACHO_ARM64_RELOC_PAGEOFF12   = 4
   105  	MACHO_ARM64_RELOC_ADDEND      = 10
   106  	MACHO_GENERIC_RELOC_VANILLA   = 0
   107  	MACHO_FAKE_GOTPCREL           = 100
   108  )
   109  
   110  const (
   111  	MH_MAGIC    = 0xfeedface
   112  	MH_MAGIC_64 = 0xfeedfacf
   113  
   114  	MH_OBJECT  = 0x1
   115  	MH_EXECUTE = 0x2
   116  
   117  	MH_NOUNDEFS = 0x1
   118  )
   119  
   120  const (
   121  	LC_SEGMENT                  = 0x1
   122  	LC_SYMTAB                   = 0x2
   123  	LC_SYMSEG                   = 0x3
   124  	LC_THREAD                   = 0x4
   125  	LC_UNIXTHREAD               = 0x5
   126  	LC_LOADFVMLIB               = 0x6
   127  	LC_IDFVMLIB                 = 0x7
   128  	LC_IDENT                    = 0x8
   129  	LC_FVMFILE                  = 0x9
   130  	LC_PREPAGE                  = 0xa
   131  	LC_DYSYMTAB                 = 0xb
   132  	LC_LOAD_DYLIB               = 0xc
   133  	LC_ID_DYLIB                 = 0xd
   134  	LC_LOAD_DYLINKER            = 0xe
   135  	LC_ID_DYLINKER              = 0xf
   136  	LC_PREBOUND_DYLIB           = 0x10
   137  	LC_ROUTINES                 = 0x11
   138  	LC_SUB_FRAMEWORK            = 0x12
   139  	LC_SUB_UMBRELLA             = 0x13
   140  	LC_SUB_CLIENT               = 0x14
   141  	LC_SUB_LIBRARY              = 0x15
   142  	LC_TWOLEVEL_HINTS           = 0x16
   143  	LC_PREBIND_CKSUM            = 0x17
   144  	LC_LOAD_WEAK_DYLIB          = 0x80000018
   145  	LC_SEGMENT_64               = 0x19
   146  	LC_ROUTINES_64              = 0x1a
   147  	LC_UUID                     = 0x1b
   148  	LC_RPATH                    = 0x8000001c
   149  	LC_CODE_SIGNATURE           = 0x1d
   150  	LC_SEGMENT_SPLIT_INFO       = 0x1e
   151  	LC_REEXPORT_DYLIB           = 0x8000001f
   152  	LC_LAZY_LOAD_DYLIB          = 0x20
   153  	LC_ENCRYPTION_INFO          = 0x21
   154  	LC_DYLD_INFO                = 0x22
   155  	LC_DYLD_INFO_ONLY           = 0x80000022
   156  	LC_LOAD_UPWARD_DYLIB        = 0x80000023
   157  	LC_VERSION_MIN_MACOSX       = 0x24
   158  	LC_VERSION_MIN_IPHONEOS     = 0x25
   159  	LC_FUNCTION_STARTS          = 0x26
   160  	LC_DYLD_ENVIRONMENT         = 0x27
   161  	LC_MAIN                     = 0x80000028
   162  	LC_DATA_IN_CODE             = 0x29
   163  	LC_SOURCE_VERSION           = 0x2A
   164  	LC_DYLIB_CODE_SIGN_DRS      = 0x2B
   165  	LC_ENCRYPTION_INFO_64       = 0x2C
   166  	LC_LINKER_OPTION            = 0x2D
   167  	LC_LINKER_OPTIMIZATION_HINT = 0x2E
   168  	LC_VERSION_MIN_TVOS         = 0x2F
   169  	LC_VERSION_MIN_WATCHOS      = 0x30
   170  	LC_VERSION_NOTE             = 0x31
   171  	LC_BUILD_VERSION            = 0x32
   172  )
   173  
   174  const (
   175  	S_REGULAR                  = 0x0
   176  	S_ZEROFILL                 = 0x1
   177  	S_NON_LAZY_SYMBOL_POINTERS = 0x6
   178  	S_SYMBOL_STUBS             = 0x8
   179  	S_MOD_INIT_FUNC_POINTERS   = 0x9
   180  	S_ATTR_PURE_INSTRUCTIONS   = 0x80000000
   181  	S_ATTR_DEBUG               = 0x02000000
   182  	S_ATTR_SOME_INSTRUCTIONS   = 0x00000400
   183  )
   184  
   185  const (
   186  	PLATFORM_MACOS    MachoPlatform = 1
   187  	PLATFORM_IOS      MachoPlatform = 2
   188  	PLATFORM_TVOS     MachoPlatform = 3
   189  	PLATFORM_WATCHOS  MachoPlatform = 4
   190  	PLATFORM_BRIDGEOS MachoPlatform = 5
   191  )
   192  
   193  // Mach-O file writing
   194  // https://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
   195  
   196  var machohdr MachoHdr
   197  
   198  var load []MachoLoad
   199  
   200  var machoPlatform MachoPlatform
   201  
   202  var seg [16]MachoSeg
   203  
   204  var nseg int
   205  
   206  var ndebug int
   207  
   208  var nsect int
   209  
   210  const (
   211  	SymKindLocal = 0 + iota
   212  	SymKindExtdef
   213  	SymKindUndef
   214  	NumSymKind
   215  )
   216  
   217  var nkind [NumSymKind]int
   218  
   219  var sortsym []*sym.Symbol
   220  
   221  var nsortsym int
   222  
   223  // Amount of space left for adding load commands
   224  // that refer to dynamic libraries. Because these have
   225  // to go in the Mach-O header, we can't just pick a
   226  // "big enough" header size. The initial header is
   227  // one page, the non-dynamic library stuff takes
   228  // up about 1300 bytes; we overestimate that as 2k.
   229  var loadBudget = INITIAL_MACHO_HEADR - 2*1024
   230  
   231  func getMachoHdr() *MachoHdr {
   232  	return &machohdr
   233  }
   234  
   235  func newMachoLoad(arch *sys.Arch, type_ uint32, ndata uint32) *MachoLoad {
   236  	if arch.PtrSize == 8 && (ndata&1 != 0) {
   237  		ndata++
   238  	}
   239  
   240  	load = append(load, MachoLoad{})
   241  	l := &load[len(load)-1]
   242  	l.type_ = type_
   243  	l.data = make([]uint32, ndata)
   244  	return l
   245  }
   246  
   247  func newMachoSeg(name string, msect int) *MachoSeg {
   248  	if nseg >= len(seg) {
   249  		Exitf("too many segs")
   250  	}
   251  
   252  	s := &seg[nseg]
   253  	nseg++
   254  	s.name = name
   255  	s.msect = uint32(msect)
   256  	s.sect = make([]MachoSect, msect)
   257  	return s
   258  }
   259  
   260  func newMachoSect(seg *MachoSeg, name string, segname string) *MachoSect {
   261  	if seg.nsect >= seg.msect {
   262  		Exitf("too many sects in segment %s", seg.name)
   263  	}
   264  
   265  	s := &seg.sect[seg.nsect]
   266  	seg.nsect++
   267  	s.name = name
   268  	s.segname = segname
   269  	nsect++
   270  	return s
   271  }
   272  
   273  // Generic linking code.
   274  
   275  var dylib []string
   276  
   277  var linkoff int64
   278  
   279  func machowrite(arch *sys.Arch, out *OutBuf, linkmode LinkMode) int {
   280  	o1 := out.Offset()
   281  
   282  	loadsize := 4 * 4 * ndebug
   283  	for i := range load {
   284  		loadsize += 4 * (len(load[i].data) + 2)
   285  	}
   286  	if arch.PtrSize == 8 {
   287  		loadsize += 18 * 4 * nseg
   288  		loadsize += 20 * 4 * nsect
   289  	} else {
   290  		loadsize += 14 * 4 * nseg
   291  		loadsize += 17 * 4 * nsect
   292  	}
   293  
   294  	if arch.PtrSize == 8 {
   295  		out.Write32(MH_MAGIC_64)
   296  	} else {
   297  		out.Write32(MH_MAGIC)
   298  	}
   299  	out.Write32(machohdr.cpu)
   300  	out.Write32(machohdr.subcpu)
   301  	if linkmode == LinkExternal {
   302  		out.Write32(MH_OBJECT) /* file type - mach object */
   303  	} else {
   304  		out.Write32(MH_EXECUTE) /* file type - mach executable */
   305  	}
   306  	out.Write32(uint32(len(load)) + uint32(nseg) + uint32(ndebug))
   307  	out.Write32(uint32(loadsize))
   308  	if nkind[SymKindUndef] == 0 {
   309  		out.Write32(MH_NOUNDEFS) /* flags - no undefines */
   310  	} else {
   311  		out.Write32(0) /* flags */
   312  	}
   313  	if arch.PtrSize == 8 {
   314  		out.Write32(0) /* reserved */
   315  	}
   316  
   317  	for i := 0; i < nseg; i++ {
   318  		s := &seg[i]
   319  		if arch.PtrSize == 8 {
   320  			out.Write32(LC_SEGMENT_64)
   321  			out.Write32(72 + 80*s.nsect)
   322  			out.WriteStringN(s.name, 16)
   323  			out.Write64(s.vaddr)
   324  			out.Write64(s.vsize)
   325  			out.Write64(s.fileoffset)
   326  			out.Write64(s.filesize)
   327  			out.Write32(s.prot1)
   328  			out.Write32(s.prot2)
   329  			out.Write32(s.nsect)
   330  			out.Write32(s.flag)
   331  		} else {
   332  			out.Write32(LC_SEGMENT)
   333  			out.Write32(56 + 68*s.nsect)
   334  			out.WriteStringN(s.name, 16)
   335  			out.Write32(uint32(s.vaddr))
   336  			out.Write32(uint32(s.vsize))
   337  			out.Write32(uint32(s.fileoffset))
   338  			out.Write32(uint32(s.filesize))
   339  			out.Write32(s.prot1)
   340  			out.Write32(s.prot2)
   341  			out.Write32(s.nsect)
   342  			out.Write32(s.flag)
   343  		}
   344  
   345  		for j := uint32(0); j < s.nsect; j++ {
   346  			t := &s.sect[j]
   347  			if arch.PtrSize == 8 {
   348  				out.WriteStringN(t.name, 16)
   349  				out.WriteStringN(t.segname, 16)
   350  				out.Write64(t.addr)
   351  				out.Write64(t.size)
   352  				out.Write32(t.off)
   353  				out.Write32(t.align)
   354  				out.Write32(t.reloc)
   355  				out.Write32(t.nreloc)
   356  				out.Write32(t.flag)
   357  				out.Write32(t.res1) /* reserved */
   358  				out.Write32(t.res2) /* reserved */
   359  				out.Write32(0)      /* reserved */
   360  			} else {
   361  				out.WriteStringN(t.name, 16)
   362  				out.WriteStringN(t.segname, 16)
   363  				out.Write32(uint32(t.addr))
   364  				out.Write32(uint32(t.size))
   365  				out.Write32(t.off)
   366  				out.Write32(t.align)
   367  				out.Write32(t.reloc)
   368  				out.Write32(t.nreloc)
   369  				out.Write32(t.flag)
   370  				out.Write32(t.res1) /* reserved */
   371  				out.Write32(t.res2) /* reserved */
   372  			}
   373  		}
   374  	}
   375  
   376  	for i := range load {
   377  		l := &load[i]
   378  		out.Write32(l.type_)
   379  		out.Write32(4 * (uint32(len(l.data)) + 2))
   380  		for j := 0; j < len(l.data); j++ {
   381  			out.Write32(l.data[j])
   382  		}
   383  	}
   384  
   385  	return int(out.Offset() - o1)
   386  }
   387  
   388  func (ctxt *Link) domacho() {
   389  	if *FlagD {
   390  		return
   391  	}
   392  
   393  	// Copy platform load command.
   394  	for _, h := range hostobj {
   395  		load, err := hostobjMachoPlatform(&h)
   396  		if err != nil {
   397  			Exitf("%v", err)
   398  		}
   399  		if load != nil {
   400  			machoPlatform = load.platform
   401  			ml := newMachoLoad(ctxt.Arch, load.cmd.type_, uint32(len(load.cmd.data)))
   402  			copy(ml.data, load.cmd.data)
   403  			break
   404  		}
   405  	}
   406  	if machoPlatform == 0 {
   407  		switch ctxt.Arch.Family {
   408  		default:
   409  			machoPlatform = PLATFORM_MACOS
   410  			if ctxt.LinkMode == LinkInternal {
   411  				// For lldb, must say LC_VERSION_MIN_MACOSX or else
   412  				// it won't know that this Mach-O binary is from OS X
   413  				// (could be iOS or WatchOS instead).
   414  				// Go on iOS uses linkmode=external, and linkmode=external
   415  				// adds this itself. So we only need this code for linkmode=internal
   416  				// and we can assume OS X.
   417  				//
   418  				// See golang.org/issues/12941.
   419  				//
   420  				// The version must be at least 10.9; see golang.org/issues/30488.
   421  				ml := newMachoLoad(ctxt.Arch, LC_VERSION_MIN_MACOSX, 2)
   422  				ml.data[0] = 10<<16 | 9<<8 | 0<<0 // OS X version 10.9.0
   423  				ml.data[1] = 10<<16 | 9<<8 | 0<<0 // SDK 10.9.0
   424  			}
   425  		case sys.ARM, sys.ARM64:
   426  			machoPlatform = PLATFORM_IOS
   427  		}
   428  	}
   429  
   430  	// empirically, string table must begin with " \x00".
   431  	s := ctxt.Syms.Lookup(".machosymstr", 0)
   432  
   433  	s.Type = sym.SMACHOSYMSTR
   434  	s.Attr |= sym.AttrReachable
   435  	s.AddUint8(' ')
   436  	s.AddUint8('\x00')
   437  
   438  	s = ctxt.Syms.Lookup(".machosymtab", 0)
   439  	s.Type = sym.SMACHOSYMTAB
   440  	s.Attr |= sym.AttrReachable
   441  
   442  	if ctxt.LinkMode != LinkExternal {
   443  		s := ctxt.Syms.Lookup(".plt", 0) // will be __symbol_stub
   444  		s.Type = sym.SMACHOPLT
   445  		s.Attr |= sym.AttrReachable
   446  
   447  		s = ctxt.Syms.Lookup(".got", 0) // will be __nl_symbol_ptr
   448  		s.Type = sym.SMACHOGOT
   449  		s.Attr |= sym.AttrReachable
   450  		s.Align = 4
   451  
   452  		s = ctxt.Syms.Lookup(".linkedit.plt", 0) // indirect table for .plt
   453  		s.Type = sym.SMACHOINDIRECTPLT
   454  		s.Attr |= sym.AttrReachable
   455  
   456  		s = ctxt.Syms.Lookup(".linkedit.got", 0) // indirect table for .got
   457  		s.Type = sym.SMACHOINDIRECTGOT
   458  		s.Attr |= sym.AttrReachable
   459  	}
   460  
   461  	// Add a dummy symbol that will become the __asm marker section.
   462  	if ctxt.LinkMode == LinkExternal {
   463  		s := ctxt.Syms.Lookup(".llvmasm", 0)
   464  		s.Type = sym.SMACHO
   465  		s.Attr |= sym.AttrReachable
   466  		s.AddUint8(0)
   467  	}
   468  }
   469  
   470  func machoadddynlib(lib string, linkmode LinkMode) {
   471  	if seenlib[lib] || linkmode == LinkExternal {
   472  		return
   473  	}
   474  	seenlib[lib] = true
   475  
   476  	// Will need to store the library name rounded up
   477  	// and 24 bytes of header metadata. If not enough
   478  	// space, grab another page of initial space at the
   479  	// beginning of the output file.
   480  	loadBudget -= (len(lib)+7)/8*8 + 24
   481  
   482  	if loadBudget < 0 {
   483  		HEADR += 4096
   484  		*FlagTextAddr += 4096
   485  		loadBudget += 4096
   486  	}
   487  
   488  	dylib = append(dylib, lib)
   489  }
   490  
   491  func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) {
   492  	buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
   493  
   494  	var msect *MachoSect
   495  	if sect.Rwx&1 == 0 && segname != "__DWARF" && (ctxt.Arch.Family == sys.ARM64 ||
   496  		ctxt.Arch.Family == sys.ARM ||
   497  		(ctxt.Arch.Family == sys.AMD64 && ctxt.BuildMode != BuildModeExe)) {
   498  		// Darwin external linker on arm and arm64, and on amd64 in c-shared/c-archive buildmode
   499  		// complains about absolute relocs in __TEXT, so if the section is not
   500  		// executable, put it in __DATA segment.
   501  		msect = newMachoSect(mseg, buf, "__DATA")
   502  	} else {
   503  		msect = newMachoSect(mseg, buf, segname)
   504  	}
   505  
   506  	if sect.Rellen > 0 {
   507  		msect.reloc = uint32(sect.Reloff)
   508  		msect.nreloc = uint32(sect.Rellen / 8)
   509  	}
   510  
   511  	for 1<<msect.align < sect.Align {
   512  		msect.align++
   513  	}
   514  	msect.addr = sect.Vaddr
   515  	msect.size = sect.Length
   516  
   517  	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
   518  		// data in file
   519  		if sect.Length > sect.Seg.Vaddr+sect.Seg.Filelen-sect.Vaddr {
   520  			Errorf(nil, "macho cannot represent section %s crossing data and bss", sect.Name)
   521  		}
   522  		msect.off = uint32(sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr)
   523  	} else {
   524  		msect.off = 0
   525  		msect.flag |= S_ZEROFILL
   526  	}
   527  
   528  	if sect.Rwx&1 != 0 {
   529  		msect.flag |= S_ATTR_SOME_INSTRUCTIONS
   530  	}
   531  
   532  	if sect.Name == ".text" {
   533  		msect.flag |= S_ATTR_PURE_INSTRUCTIONS
   534  	}
   535  
   536  	if sect.Name == ".plt" {
   537  		msect.name = "__symbol_stub1"
   538  		msect.flag = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS | S_SYMBOL_STUBS
   539  		msect.res1 = 0 //nkind[SymKindLocal];
   540  		msect.res2 = 6
   541  	}
   542  
   543  	if sect.Name == ".got" {
   544  		msect.name = "__nl_symbol_ptr"
   545  		msect.flag = S_NON_LAZY_SYMBOL_POINTERS
   546  		msect.res1 = uint32(ctxt.Syms.Lookup(".linkedit.plt", 0).Size / 4) /* offset into indirect symbol table */
   547  	}
   548  
   549  	if sect.Name == ".init_array" {
   550  		msect.name = "__mod_init_func"
   551  		msect.flag = S_MOD_INIT_FUNC_POINTERS
   552  	}
   553  
   554  	// Some platforms such as watchOS and tvOS require binaries with
   555  	// bitcode enabled. The Go toolchain can't output bitcode, so use
   556  	// a marker section in the __LLVM segment, "__asm", to tell the Apple
   557  	// toolchain that the Go text came from assembler and thus has no
   558  	// bitcode. This is not true, but Kotlin/Native, Rust and Flutter
   559  	// are also using this trick.
   560  	if sect.Name == ".llvmasm" {
   561  		msect.name = "__asm"
   562  		msect.segname = "__LLVM"
   563  	}
   564  
   565  	if segname == "__DWARF" {
   566  		msect.flag |= S_ATTR_DEBUG
   567  	}
   568  }
   569  
   570  func Asmbmacho(ctxt *Link) {
   571  	/* apple MACH */
   572  	va := *FlagTextAddr - int64(HEADR)
   573  
   574  	mh := getMachoHdr()
   575  	switch ctxt.Arch.Family {
   576  	default:
   577  		Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
   578  
   579  	case sys.ARM:
   580  		mh.cpu = MACHO_CPU_ARM
   581  		mh.subcpu = MACHO_SUBCPU_ARMV7
   582  
   583  	case sys.AMD64:
   584  		mh.cpu = MACHO_CPU_AMD64
   585  		mh.subcpu = MACHO_SUBCPU_X86
   586  
   587  	case sys.ARM64:
   588  		mh.cpu = MACHO_CPU_ARM64
   589  		mh.subcpu = MACHO_SUBCPU_ARM64_ALL
   590  
   591  	case sys.I386:
   592  		mh.cpu = MACHO_CPU_386
   593  		mh.subcpu = MACHO_SUBCPU_X86
   594  	}
   595  
   596  	var ms *MachoSeg
   597  	if ctxt.LinkMode == LinkExternal {
   598  		/* segment for entire file */
   599  		ms = newMachoSeg("", 40)
   600  
   601  		ms.fileoffset = Segtext.Fileoff
   602  		ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
   603  		ms.vsize = Segdwarf.Vaddr + Segdwarf.Length - Segtext.Vaddr
   604  	}
   605  
   606  	/* segment for zero page */
   607  	if ctxt.LinkMode != LinkExternal {
   608  		ms = newMachoSeg("__PAGEZERO", 0)
   609  		ms.vsize = uint64(va)
   610  	}
   611  
   612  	/* text */
   613  	v := Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound))
   614  
   615  	if ctxt.LinkMode != LinkExternal {
   616  		ms = newMachoSeg("__TEXT", 20)
   617  		ms.vaddr = uint64(va)
   618  		ms.vsize = uint64(v)
   619  		ms.fileoffset = 0
   620  		ms.filesize = uint64(v)
   621  		ms.prot1 = 7
   622  		ms.prot2 = 5
   623  	}
   624  
   625  	for _, sect := range Segtext.Sections {
   626  		machoshbits(ctxt, ms, sect, "__TEXT")
   627  	}
   628  
   629  	/* data */
   630  	if ctxt.LinkMode != LinkExternal {
   631  		w := int64(Segdata.Length)
   632  		ms = newMachoSeg("__DATA", 20)
   633  		ms.vaddr = uint64(va) + uint64(v)
   634  		ms.vsize = uint64(w)
   635  		ms.fileoffset = uint64(v)
   636  		ms.filesize = Segdata.Filelen
   637  		ms.prot1 = 3
   638  		ms.prot2 = 3
   639  	}
   640  
   641  	for _, sect := range Segdata.Sections {
   642  		machoshbits(ctxt, ms, sect, "__DATA")
   643  	}
   644  
   645  	/* dwarf */
   646  	if !*FlagW {
   647  		if ctxt.LinkMode != LinkExternal {
   648  			ms = newMachoSeg("__DWARF", 20)
   649  			ms.vaddr = Segdwarf.Vaddr
   650  			ms.vsize = 0
   651  			ms.fileoffset = Segdwarf.Fileoff
   652  			ms.filesize = Segdwarf.Filelen
   653  		}
   654  		for _, sect := range Segdwarf.Sections {
   655  			machoshbits(ctxt, ms, sect, "__DWARF")
   656  		}
   657  	}
   658  
   659  	if ctxt.LinkMode != LinkExternal {
   660  		switch ctxt.Arch.Family {
   661  		default:
   662  			Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
   663  
   664  		case sys.ARM:
   665  			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 17+2)
   666  			ml.data[0] = 1                           /* thread type */
   667  			ml.data[1] = 17                          /* word count */
   668  			ml.data[2+15] = uint32(Entryvalue(ctxt)) /* start pc */
   669  
   670  		case sys.AMD64:
   671  			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 42+2)
   672  			ml.data[0] = 4                           /* thread type */
   673  			ml.data[1] = 42                          /* word count */
   674  			ml.data[2+32] = uint32(Entryvalue(ctxt)) /* start pc */
   675  			ml.data[2+32+1] = uint32(Entryvalue(ctxt) >> 32)
   676  
   677  		case sys.ARM64:
   678  			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 68+2)
   679  			ml.data[0] = 6                           /* thread type */
   680  			ml.data[1] = 68                          /* word count */
   681  			ml.data[2+64] = uint32(Entryvalue(ctxt)) /* start pc */
   682  			ml.data[2+64+1] = uint32(Entryvalue(ctxt) >> 32)
   683  
   684  		case sys.I386:
   685  			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 16+2)
   686  			ml.data[0] = 1                           /* thread type */
   687  			ml.data[1] = 16                          /* word count */
   688  			ml.data[2+10] = uint32(Entryvalue(ctxt)) /* start pc */
   689  		}
   690  	}
   691  
   692  	if !*FlagD {
   693  		// must match domacholink below
   694  		s1 := ctxt.Syms.Lookup(".machosymtab", 0)
   695  		s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
   696  		s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
   697  		s4 := ctxt.Syms.Lookup(".machosymstr", 0)
   698  
   699  		if ctxt.LinkMode != LinkExternal {
   700  			ms := newMachoSeg("__LINKEDIT", 0)
   701  			ms.vaddr = uint64(va) + uint64(v) + uint64(Rnd(int64(Segdata.Length), int64(*FlagRound)))
   702  			ms.vsize = uint64(s1.Size) + uint64(s2.Size) + uint64(s3.Size) + uint64(s4.Size)
   703  			ms.fileoffset = uint64(linkoff)
   704  			ms.filesize = ms.vsize
   705  			ms.prot1 = 7
   706  			ms.prot2 = 3
   707  		}
   708  
   709  		ml := newMachoLoad(ctxt.Arch, LC_SYMTAB, 4)
   710  		ml.data[0] = uint32(linkoff)                               /* symoff */
   711  		ml.data[1] = uint32(nsortsym)                              /* nsyms */
   712  		ml.data[2] = uint32(linkoff + s1.Size + s2.Size + s3.Size) /* stroff */
   713  		ml.data[3] = uint32(s4.Size)                               /* strsize */
   714  
   715  		machodysymtab(ctxt)
   716  
   717  		if ctxt.LinkMode != LinkExternal {
   718  			ml := newMachoLoad(ctxt.Arch, LC_LOAD_DYLINKER, 6)
   719  			ml.data[0] = 12 /* offset to string */
   720  			stringtouint32(ml.data[1:], "/usr/lib/dyld")
   721  
   722  			for _, lib := range dylib {
   723  				ml = newMachoLoad(ctxt.Arch, LC_LOAD_DYLIB, 4+(uint32(len(lib))+1+7)/8*2)
   724  				ml.data[0] = 24 /* offset of string from beginning of load */
   725  				ml.data[1] = 0  /* time stamp */
   726  				ml.data[2] = 0  /* version */
   727  				ml.data[3] = 0  /* compatibility version */
   728  				stringtouint32(ml.data[4:], lib)
   729  			}
   730  		}
   731  	}
   732  
   733  	a := machowrite(ctxt.Arch, ctxt.Out, ctxt.LinkMode)
   734  	if int32(a) > HEADR {
   735  		Exitf("HEADR too small: %d > %d", a, HEADR)
   736  	}
   737  }
   738  
   739  func symkind(s *sym.Symbol) int {
   740  	if s.Type == sym.SDYNIMPORT {
   741  		return SymKindUndef
   742  	}
   743  	if s.Attr.CgoExport() {
   744  		return SymKindExtdef
   745  	}
   746  	return SymKindLocal
   747  }
   748  
   749  func addsym(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) {
   750  	if s == nil {
   751  		return
   752  	}
   753  
   754  	switch type_ {
   755  	default:
   756  		return
   757  
   758  	case DataSym, BSSSym, TextSym:
   759  		break
   760  	}
   761  
   762  	if sortsym != nil {
   763  		sortsym[nsortsym] = s
   764  		nkind[symkind(s)]++
   765  	}
   766  
   767  	nsortsym++
   768  }
   769  
   770  type machoscmp []*sym.Symbol
   771  
   772  func (x machoscmp) Len() int {
   773  	return len(x)
   774  }
   775  
   776  func (x machoscmp) Swap(i, j int) {
   777  	x[i], x[j] = x[j], x[i]
   778  }
   779  
   780  func (x machoscmp) Less(i, j int) bool {
   781  	s1 := x[i]
   782  	s2 := x[j]
   783  
   784  	k1 := symkind(s1)
   785  	k2 := symkind(s2)
   786  	if k1 != k2 {
   787  		return k1 < k2
   788  	}
   789  
   790  	return s1.Extname() < s2.Extname()
   791  }
   792  
   793  func machogenasmsym(ctxt *Link) {
   794  	genasmsym(ctxt, addsym)
   795  	for _, s := range ctxt.Syms.Allsym {
   796  		// Some 64-bit functions have a "$INODE64" or "$INODE64$UNIX2003" suffix.
   797  		if s.Type == sym.SDYNIMPORT && s.Dynimplib() == "/usr/lib/libSystem.B.dylib" {
   798  			// But only on macOS.
   799  			if machoPlatform == PLATFORM_MACOS {
   800  				switch n := s.Extname(); n {
   801  				case "fdopendir":
   802  					switch objabi.GOARCH {
   803  					case "amd64":
   804  						s.SetExtname(n + "$INODE64")
   805  					case "386":
   806  						s.SetExtname(n + "$INODE64$UNIX2003")
   807  					}
   808  				case "readdir_r", "getfsstat":
   809  					switch objabi.GOARCH {
   810  					case "amd64", "386":
   811  						s.SetExtname(n + "$INODE64")
   812  					}
   813  				}
   814  			}
   815  		}
   816  
   817  		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
   818  			if s.Attr.Reachable() {
   819  				addsym(ctxt, s, "", DataSym, 0, nil)
   820  			}
   821  		}
   822  	}
   823  }
   824  
   825  func machosymorder(ctxt *Link) {
   826  	// On Mac OS X Mountain Lion, we must sort exported symbols
   827  	// So we sort them here and pre-allocate dynid for them
   828  	// See https://golang.org/issue/4029
   829  	for i := range dynexp {
   830  		dynexp[i].Attr |= sym.AttrReachable
   831  	}
   832  	machogenasmsym(ctxt)
   833  	sortsym = make([]*sym.Symbol, nsortsym)
   834  	nsortsym = 0
   835  	machogenasmsym(ctxt)
   836  	sort.Sort(machoscmp(sortsym[:nsortsym]))
   837  	for i := 0; i < nsortsym; i++ {
   838  		sortsym[i].Dynid = int32(i)
   839  	}
   840  }
   841  
   842  // machoShouldExport reports whether a symbol needs to be exported.
   843  //
   844  // When dynamically linking, all non-local variables and plugin-exported
   845  // symbols need to be exported.
   846  func machoShouldExport(ctxt *Link, s *sym.Symbol) bool {
   847  	if !ctxt.DynlinkingGo() || s.Attr.Local() {
   848  		return false
   849  	}
   850  	if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(s.Extname(), objabi.PathToPrefix(*flagPluginPath)) {
   851  		return true
   852  	}
   853  	if strings.HasPrefix(s.Name, "go.itab.") {
   854  		return true
   855  	}
   856  	if strings.HasPrefix(s.Name, "type.") && !strings.HasPrefix(s.Name, "type..") {
   857  		// reduce runtime typemap pressure, but do not
   858  		// export alg functions (type..*), as these
   859  		// appear in pclntable.
   860  		return true
   861  	}
   862  	if strings.HasPrefix(s.Name, "go.link.pkghash") {
   863  		return true
   864  	}
   865  	return s.Type >= sym.SFirstWritable // only writable sections
   866  }
   867  
   868  func machosymtab(ctxt *Link) {
   869  	symtab := ctxt.Syms.Lookup(".machosymtab", 0)
   870  	symstr := ctxt.Syms.Lookup(".machosymstr", 0)
   871  
   872  	for i := 0; i < nsortsym; i++ {
   873  		s := sortsym[i]
   874  		symtab.AddUint32(ctxt.Arch, uint32(symstr.Size))
   875  
   876  		export := machoShouldExport(ctxt, s)
   877  		isGoSymbol := strings.Contains(s.Extname(), ".")
   878  
   879  		// In normal buildmodes, only add _ to C symbols, as
   880  		// Go symbols have dot in the name.
   881  		//
   882  		// Do not export C symbols in plugins, as runtime C
   883  		// symbols like crosscall2 are in pclntab and end up
   884  		// pointing at the host binary, breaking unwinding.
   885  		// See Issue #18190.
   886  		cexport := !isGoSymbol && (ctxt.BuildMode != BuildModePlugin || onlycsymbol(s))
   887  		if cexport || export || isGoSymbol {
   888  			symstr.AddUint8('_')
   889  		}
   890  
   891  		// replace "·" as ".", because DTrace cannot handle it.
   892  		Addstring(symstr, strings.Replace(s.Extname(), "·", ".", -1))
   893  
   894  		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
   895  			symtab.AddUint8(0x01)                             // type N_EXT, external symbol
   896  			symtab.AddUint8(0)                                // no section
   897  			symtab.AddUint16(ctxt.Arch, 0)                    // desc
   898  			symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value
   899  		} else {
   900  			if s.Attr.CgoExport() || export {
   901  				symtab.AddUint8(0x0f)
   902  			} else {
   903  				symtab.AddUint8(0x0e)
   904  			}
   905  			o := s
   906  			for o.Outer != nil {
   907  				o = o.Outer
   908  			}
   909  			if o.Sect == nil {
   910  				Errorf(s, "missing section for symbol")
   911  				symtab.AddUint8(0)
   912  			} else {
   913  				symtab.AddUint8(uint8(o.Sect.Extnum))
   914  			}
   915  			symtab.AddUint16(ctxt.Arch, 0) // desc
   916  			symtab.AddUintXX(ctxt.Arch, uint64(Symaddr(s)), ctxt.Arch.PtrSize)
   917  		}
   918  	}
   919  }
   920  
   921  func machodysymtab(ctxt *Link) {
   922  	ml := newMachoLoad(ctxt.Arch, LC_DYSYMTAB, 18)
   923  
   924  	n := 0
   925  	ml.data[0] = uint32(n)                   /* ilocalsym */
   926  	ml.data[1] = uint32(nkind[SymKindLocal]) /* nlocalsym */
   927  	n += nkind[SymKindLocal]
   928  
   929  	ml.data[2] = uint32(n)                    /* iextdefsym */
   930  	ml.data[3] = uint32(nkind[SymKindExtdef]) /* nextdefsym */
   931  	n += nkind[SymKindExtdef]
   932  
   933  	ml.data[4] = uint32(n)                   /* iundefsym */
   934  	ml.data[5] = uint32(nkind[SymKindUndef]) /* nundefsym */
   935  
   936  	ml.data[6] = 0  /* tocoffset */
   937  	ml.data[7] = 0  /* ntoc */
   938  	ml.data[8] = 0  /* modtaboff */
   939  	ml.data[9] = 0  /* nmodtab */
   940  	ml.data[10] = 0 /* extrefsymoff */
   941  	ml.data[11] = 0 /* nextrefsyms */
   942  
   943  	// must match domacholink below
   944  	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
   945  
   946  	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
   947  	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
   948  	ml.data[12] = uint32(linkoff + s1.Size)       /* indirectsymoff */
   949  	ml.data[13] = uint32((s2.Size + s3.Size) / 4) /* nindirectsyms */
   950  
   951  	ml.data[14] = 0 /* extreloff */
   952  	ml.data[15] = 0 /* nextrel */
   953  	ml.data[16] = 0 /* locreloff */
   954  	ml.data[17] = 0 /* nlocrel */
   955  }
   956  
   957  func Domacholink(ctxt *Link) int64 {
   958  	machosymtab(ctxt)
   959  
   960  	// write data that will be linkedit section
   961  	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
   962  
   963  	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
   964  	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
   965  	s4 := ctxt.Syms.Lookup(".machosymstr", 0)
   966  
   967  	// Force the linkedit section to end on a 16-byte
   968  	// boundary. This allows pure (non-cgo) Go binaries
   969  	// to be code signed correctly.
   970  	//
   971  	// Apple's codesign_allocate (a helper utility for
   972  	// the codesign utility) can do this fine itself if
   973  	// it is run on a dynamic Mach-O binary. However,
   974  	// when it is run on a pure (non-cgo) Go binary, where
   975  	// the linkedit section is mostly empty, it fails to
   976  	// account for the extra padding that it itself adds
   977  	// when adding the LC_CODE_SIGNATURE load command
   978  	// (which must be aligned on a 16-byte boundary).
   979  	//
   980  	// By forcing the linkedit section to end on a 16-byte
   981  	// boundary, codesign_allocate will not need to apply
   982  	// any alignment padding itself, working around the
   983  	// issue.
   984  	for s4.Size%16 != 0 {
   985  		s4.AddUint8(0)
   986  	}
   987  
   988  	size := int(s1.Size + s2.Size + s3.Size + s4.Size)
   989  
   990  	if size > 0 {
   991  		linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))
   992  		ctxt.Out.SeekSet(linkoff)
   993  
   994  		ctxt.Out.Write(s1.P[:s1.Size])
   995  		ctxt.Out.Write(s2.P[:s2.Size])
   996  		ctxt.Out.Write(s3.P[:s3.Size])
   997  		ctxt.Out.Write(s4.P[:s4.Size])
   998  	}
   999  
  1000  	return Rnd(int64(size), int64(*FlagRound))
  1001  }
  1002  
  1003  func machorelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
  1004  	// If main section has no bits, nothing to relocate.
  1005  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1006  		return
  1007  	}
  1008  
  1009  	sect.Reloff = uint64(ctxt.Out.Offset())
  1010  	for i, s := range syms {
  1011  		if !s.Attr.Reachable() {
  1012  			continue
  1013  		}
  1014  		if uint64(s.Value) >= sect.Vaddr {
  1015  			syms = syms[i:]
  1016  			break
  1017  		}
  1018  	}
  1019  
  1020  	eaddr := int32(sect.Vaddr + sect.Length)
  1021  	for _, s := range syms {
  1022  		if !s.Attr.Reachable() {
  1023  			continue
  1024  		}
  1025  		if s.Value >= int64(eaddr) {
  1026  			break
  1027  		}
  1028  		for ri := range s.R {
  1029  			r := &s.R[ri]
  1030  			if r.Done {
  1031  				continue
  1032  			}
  1033  			if r.Xsym == nil {
  1034  				Errorf(s, "missing xsym in relocation")
  1035  				continue
  1036  			}
  1037  			if !r.Xsym.Attr.Reachable() {
  1038  				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
  1039  			}
  1040  			if !thearch.Machoreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
  1041  				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
  1042  			}
  1043  		}
  1044  	}
  1045  
  1046  	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
  1047  }
  1048  
  1049  func Machoemitreloc(ctxt *Link) {
  1050  	for ctxt.Out.Offset()&7 != 0 {
  1051  		ctxt.Out.Write8(0)
  1052  	}
  1053  
  1054  	machorelocsect(ctxt, Segtext.Sections[0], ctxt.Textp)
  1055  	for _, sect := range Segtext.Sections[1:] {
  1056  		machorelocsect(ctxt, sect, datap)
  1057  	}
  1058  	for _, sect := range Segdata.Sections {
  1059  		machorelocsect(ctxt, sect, datap)
  1060  	}
  1061  	for _, sect := range Segdwarf.Sections {
  1062  		machorelocsect(ctxt, sect, dwarfp)
  1063  	}
  1064  }
  1065  
  1066  // hostobjMachoPlatform returns the first platform load command found
  1067  // in the host object, if any.
  1068  func hostobjMachoPlatform(h *Hostobj) (*MachoPlatformLoad, error) {
  1069  	f, err := os.Open(h.file)
  1070  	if err != nil {
  1071  		return nil, fmt.Errorf("%s: failed to open host object: %v\n", h.file, err)
  1072  	}
  1073  	defer f.Close()
  1074  	sr := io.NewSectionReader(f, h.off, h.length)
  1075  	m, err := macho.NewFile(sr)
  1076  	if err != nil {
  1077  		// Not a valid Mach-O file.
  1078  		return nil, nil
  1079  	}
  1080  	return peekMachoPlatform(m)
  1081  }
  1082  
  1083  // peekMachoPlatform returns the first LC_VERSION_MIN_* or LC_BUILD_VERSION
  1084  // load command found in the Mach-O file, if any.
  1085  func peekMachoPlatform(m *macho.File) (*MachoPlatformLoad, error) {
  1086  	for _, cmd := range m.Loads {
  1087  		raw := cmd.Raw()
  1088  		ml := MachoLoad{
  1089  			type_: m.ByteOrder.Uint32(raw),
  1090  		}
  1091  		// Skip the type and command length.
  1092  		data := raw[8:]
  1093  		var p MachoPlatform
  1094  		switch ml.type_ {
  1095  		case LC_VERSION_MIN_IPHONEOS:
  1096  			p = PLATFORM_IOS
  1097  		case LC_VERSION_MIN_MACOSX:
  1098  			p = PLATFORM_MACOS
  1099  		case LC_VERSION_MIN_WATCHOS:
  1100  			p = PLATFORM_WATCHOS
  1101  		case LC_VERSION_MIN_TVOS:
  1102  			p = PLATFORM_TVOS
  1103  		case LC_BUILD_VERSION:
  1104  			p = MachoPlatform(m.ByteOrder.Uint32(data))
  1105  		default:
  1106  			continue
  1107  		}
  1108  		ml.data = make([]uint32, len(data)/4)
  1109  		r := bytes.NewReader(data)
  1110  		if err := binary.Read(r, m.ByteOrder, &ml.data); err != nil {
  1111  			return nil, err
  1112  		}
  1113  		return &MachoPlatformLoad{
  1114  			platform: p,
  1115  			cmd:      ml,
  1116  		}, nil
  1117  	}
  1118  	return nil, nil
  1119  }