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