github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/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  // Copyright 2009 The Go Authors. All rights reserved.
   171  // Use of this source code is governed by a BSD-style
   172  // license that can be found in the LICENSE file.
   173  
   174  // Mach-O file writing
   175  // http://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
   176  
   177  var machohdr MachoHdr
   178  
   179  var load []MachoLoad
   180  
   181  var seg [16]MachoSeg
   182  
   183  var nseg int
   184  
   185  var ndebug int
   186  
   187  var nsect int
   188  
   189  const (
   190  	SymKindLocal = 0 + iota
   191  	SymKindExtdef
   192  	SymKindUndef
   193  	NumSymKind
   194  )
   195  
   196  var nkind [NumSymKind]int
   197  
   198  var sortsym []*sym.Symbol
   199  
   200  var nsortsym int
   201  
   202  // Amount of space left for adding load commands
   203  // that refer to dynamic libraries. Because these have
   204  // to go in the Mach-O header, we can't just pick a
   205  // "big enough" header size. The initial header is
   206  // one page, the non-dynamic library stuff takes
   207  // up about 1300 bytes; we overestimate that as 2k.
   208  var loadBudget = INITIAL_MACHO_HEADR - 2*1024
   209  
   210  func getMachoHdr() *MachoHdr {
   211  	return &machohdr
   212  }
   213  
   214  func newMachoLoad(arch *sys.Arch, type_ uint32, ndata uint32) *MachoLoad {
   215  	if arch.PtrSize == 8 && (ndata&1 != 0) {
   216  		ndata++
   217  	}
   218  
   219  	load = append(load, MachoLoad{})
   220  	l := &load[len(load)-1]
   221  	l.type_ = type_
   222  	l.data = make([]uint32, ndata)
   223  	return l
   224  }
   225  
   226  func newMachoSeg(name string, msect int) *MachoSeg {
   227  	if nseg >= len(seg) {
   228  		Exitf("too many segs")
   229  	}
   230  
   231  	s := &seg[nseg]
   232  	nseg++
   233  	s.name = name
   234  	s.msect = uint32(msect)
   235  	s.sect = make([]MachoSect, msect)
   236  	return s
   237  }
   238  
   239  func newMachoSect(seg *MachoSeg, name string, segname string) *MachoSect {
   240  	if seg.nsect >= seg.msect {
   241  		Exitf("too many sects in segment %s", seg.name)
   242  	}
   243  
   244  	s := &seg.sect[seg.nsect]
   245  	seg.nsect++
   246  	s.name = name
   247  	s.segname = segname
   248  	nsect++
   249  	return s
   250  }
   251  
   252  // Generic linking code.
   253  
   254  var dylib []string
   255  
   256  var linkoff int64
   257  
   258  func machowrite(arch *sys.Arch, out *OutBuf, linkmode LinkMode) int {
   259  	o1 := out.Offset()
   260  
   261  	loadsize := 4 * 4 * ndebug
   262  	for i := 0; i < len(load); i++ {
   263  		loadsize += 4 * (len(load[i].data) + 2)
   264  	}
   265  	if arch.PtrSize == 8 {
   266  		loadsize += 18 * 4 * nseg
   267  		loadsize += 20 * 4 * nsect
   268  	} else {
   269  		loadsize += 14 * 4 * nseg
   270  		loadsize += 17 * 4 * nsect
   271  	}
   272  
   273  	if arch.PtrSize == 8 {
   274  		out.Write32(MH_MAGIC_64)
   275  	} else {
   276  		out.Write32(MH_MAGIC)
   277  	}
   278  	out.Write32(machohdr.cpu)
   279  	out.Write32(machohdr.subcpu)
   280  	if linkmode == LinkExternal {
   281  		out.Write32(MH_OBJECT) /* file type - mach object */
   282  	} else {
   283  		out.Write32(MH_EXECUTE) /* file type - mach executable */
   284  	}
   285  	out.Write32(uint32(len(load)) + uint32(nseg) + uint32(ndebug))
   286  	out.Write32(uint32(loadsize))
   287  	if nkind[SymKindUndef] == 0 {
   288  		out.Write32(MH_NOUNDEFS) /* flags - no undefines */
   289  	} else {
   290  		out.Write32(0) /* flags */
   291  	}
   292  	if arch.PtrSize == 8 {
   293  		out.Write32(0) /* reserved */
   294  	}
   295  
   296  	for i := 0; i < nseg; i++ {
   297  		s := &seg[i]
   298  		if arch.PtrSize == 8 {
   299  			out.Write32(LC_SEGMENT_64)
   300  			out.Write32(72 + 80*s.nsect)
   301  			out.WriteStringN(s.name, 16)
   302  			out.Write64(s.vaddr)
   303  			out.Write64(s.vsize)
   304  			out.Write64(s.fileoffset)
   305  			out.Write64(s.filesize)
   306  			out.Write32(s.prot1)
   307  			out.Write32(s.prot2)
   308  			out.Write32(s.nsect)
   309  			out.Write32(s.flag)
   310  		} else {
   311  			out.Write32(LC_SEGMENT)
   312  			out.Write32(56 + 68*s.nsect)
   313  			out.WriteStringN(s.name, 16)
   314  			out.Write32(uint32(s.vaddr))
   315  			out.Write32(uint32(s.vsize))
   316  			out.Write32(uint32(s.fileoffset))
   317  			out.Write32(uint32(s.filesize))
   318  			out.Write32(s.prot1)
   319  			out.Write32(s.prot2)
   320  			out.Write32(s.nsect)
   321  			out.Write32(s.flag)
   322  		}
   323  
   324  		for j := uint32(0); j < s.nsect; j++ {
   325  			t := &s.sect[j]
   326  			if arch.PtrSize == 8 {
   327  				out.WriteStringN(t.name, 16)
   328  				out.WriteStringN(t.segname, 16)
   329  				out.Write64(t.addr)
   330  				out.Write64(t.size)
   331  				out.Write32(t.off)
   332  				out.Write32(t.align)
   333  				out.Write32(t.reloc)
   334  				out.Write32(t.nreloc)
   335  				out.Write32(t.flag)
   336  				out.Write32(t.res1) /* reserved */
   337  				out.Write32(t.res2) /* reserved */
   338  				out.Write32(0)      /* reserved */
   339  			} else {
   340  				out.WriteStringN(t.name, 16)
   341  				out.WriteStringN(t.segname, 16)
   342  				out.Write32(uint32(t.addr))
   343  				out.Write32(uint32(t.size))
   344  				out.Write32(t.off)
   345  				out.Write32(t.align)
   346  				out.Write32(t.reloc)
   347  				out.Write32(t.nreloc)
   348  				out.Write32(t.flag)
   349  				out.Write32(t.res1) /* reserved */
   350  				out.Write32(t.res2) /* reserved */
   351  			}
   352  		}
   353  	}
   354  
   355  	for i := 0; i < len(load); i++ {
   356  		l := &load[i]
   357  		out.Write32(l.type_)
   358  		out.Write32(4 * (uint32(len(l.data)) + 2))
   359  		for j := 0; j < len(l.data); j++ {
   360  			out.Write32(l.data[j])
   361  		}
   362  	}
   363  
   364  	return int(out.Offset() - o1)
   365  }
   366  
   367  func (ctxt *Link) domacho() {
   368  	if *FlagD {
   369  		return
   370  	}
   371  
   372  	// empirically, string table must begin with " \x00".
   373  	s := ctxt.Syms.Lookup(".machosymstr", 0)
   374  
   375  	s.Type = sym.SMACHOSYMSTR
   376  	s.Attr |= sym.AttrReachable
   377  	s.AddUint8(' ')
   378  	s.AddUint8('\x00')
   379  
   380  	s = ctxt.Syms.Lookup(".machosymtab", 0)
   381  	s.Type = sym.SMACHOSYMTAB
   382  	s.Attr |= sym.AttrReachable
   383  
   384  	if ctxt.LinkMode != LinkExternal {
   385  		s := ctxt.Syms.Lookup(".plt", 0) // will be __symbol_stub
   386  		s.Type = sym.SMACHOPLT
   387  		s.Attr |= sym.AttrReachable
   388  
   389  		s = ctxt.Syms.Lookup(".got", 0) // will be __nl_symbol_ptr
   390  		s.Type = sym.SMACHOGOT
   391  		s.Attr |= sym.AttrReachable
   392  		s.Align = 4
   393  
   394  		s = ctxt.Syms.Lookup(".linkedit.plt", 0) // indirect table for .plt
   395  		s.Type = sym.SMACHOINDIRECTPLT
   396  		s.Attr |= sym.AttrReachable
   397  
   398  		s = ctxt.Syms.Lookup(".linkedit.got", 0) // indirect table for .got
   399  		s.Type = sym.SMACHOINDIRECTGOT
   400  		s.Attr |= sym.AttrReachable
   401  	}
   402  }
   403  
   404  func machoadddynlib(lib string, linkmode LinkMode) {
   405  	if seenlib[lib] || linkmode == LinkExternal {
   406  		return
   407  	}
   408  	seenlib[lib] = true
   409  
   410  	// Will need to store the library name rounded up
   411  	// and 24 bytes of header metadata. If not enough
   412  	// space, grab another page of initial space at the
   413  	// beginning of the output file.
   414  	loadBudget -= (len(lib)+7)/8*8 + 24
   415  
   416  	if loadBudget < 0 {
   417  		HEADR += 4096
   418  		*FlagTextAddr += 4096
   419  		loadBudget += 4096
   420  	}
   421  
   422  	dylib = append(dylib, lib)
   423  }
   424  
   425  func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) {
   426  	buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
   427  
   428  	var msect *MachoSect
   429  	if sect.Rwx&1 == 0 && segname != "__DWARF" && (ctxt.Arch.Family == sys.ARM64 ||
   430  		(ctxt.Arch.Family == sys.AMD64 && ctxt.BuildMode != BuildModeExe) ||
   431  		(ctxt.Arch.Family == sys.ARM && ctxt.BuildMode != BuildModeExe)) {
   432  		// Darwin external linker on arm64 and on amd64 and arm in c-shared/c-archive buildmode
   433  		// complains about absolute relocs in __TEXT, so if the section is not
   434  		// executable, put it in __DATA segment.
   435  		msect = newMachoSect(mseg, buf, "__DATA")
   436  	} else {
   437  		msect = newMachoSect(mseg, buf, segname)
   438  	}
   439  
   440  	if sect.Rellen > 0 {
   441  		msect.reloc = uint32(sect.Reloff)
   442  		msect.nreloc = uint32(sect.Rellen / 8)
   443  	}
   444  
   445  	for 1<<msect.align < sect.Align {
   446  		msect.align++
   447  	}
   448  	msect.addr = sect.Vaddr
   449  	msect.size = sect.Length
   450  
   451  	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
   452  		// data in file
   453  		if sect.Length > sect.Seg.Vaddr+sect.Seg.Filelen-sect.Vaddr {
   454  			Errorf(nil, "macho cannot represent section %s crossing data and bss", sect.Name)
   455  		}
   456  		msect.off = uint32(sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr)
   457  	} else {
   458  		msect.off = 0
   459  		msect.flag |= S_ZEROFILL
   460  	}
   461  
   462  	if sect.Rwx&1 != 0 {
   463  		msect.flag |= S_ATTR_SOME_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 i := 0; i < len(dylib); i++ {
   646  				ml = newMachoLoad(ctxt.Arch, LC_LOAD_DYLIB, 4+(uint32(len(dylib[i]))+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:], dylib[i])
   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  		ml := newMachoLoad(ctxt.Arch, LC_VERSION_MIN_MACOSX, 2)
   666  		ml.data[0] = 10<<16 | 7<<8 | 0<<0 // OS X version 10.7.0
   667  		ml.data[1] = 10<<16 | 7<<8 | 0<<0 // SDK 10.7.0
   668  	}
   669  
   670  	a := machowrite(ctxt.Arch, ctxt.Out, ctxt.LinkMode)
   671  	if int32(a) > HEADR {
   672  		Exitf("HEADR too small: %d > %d", a, HEADR)
   673  	}
   674  }
   675  
   676  func symkind(s *sym.Symbol) int {
   677  	if s.Type == sym.SDYNIMPORT {
   678  		return SymKindUndef
   679  	}
   680  	if s.Attr.CgoExport() {
   681  		return SymKindExtdef
   682  	}
   683  	return SymKindLocal
   684  }
   685  
   686  func addsym(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) {
   687  	if s == nil {
   688  		return
   689  	}
   690  
   691  	switch type_ {
   692  	default:
   693  		return
   694  
   695  	case DataSym, BSSSym, TextSym:
   696  		break
   697  	}
   698  
   699  	if sortsym != nil {
   700  		sortsym[nsortsym] = s
   701  		nkind[symkind(s)]++
   702  	}
   703  
   704  	nsortsym++
   705  }
   706  
   707  type machoscmp []*sym.Symbol
   708  
   709  func (x machoscmp) Len() int {
   710  	return len(x)
   711  }
   712  
   713  func (x machoscmp) Swap(i, j int) {
   714  	x[i], x[j] = x[j], x[i]
   715  }
   716  
   717  func (x machoscmp) Less(i, j int) bool {
   718  	s1 := x[i]
   719  	s2 := x[j]
   720  
   721  	k1 := symkind(s1)
   722  	k2 := symkind(s2)
   723  	if k1 != k2 {
   724  		return k1 < k2
   725  	}
   726  
   727  	return s1.Extname < s2.Extname
   728  }
   729  
   730  func machogenasmsym(ctxt *Link) {
   731  	genasmsym(ctxt, addsym)
   732  	for _, s := range ctxt.Syms.Allsym {
   733  		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
   734  			if s.Attr.Reachable() {
   735  				addsym(ctxt, s, "", DataSym, 0, nil)
   736  			}
   737  		}
   738  	}
   739  }
   740  
   741  func machosymorder(ctxt *Link) {
   742  	// On Mac OS X Mountain Lion, we must sort exported symbols
   743  	// So we sort them here and pre-allocate dynid for them
   744  	// See https://golang.org/issue/4029
   745  	for i := 0; i < len(dynexp); i++ {
   746  		dynexp[i].Attr |= sym.AttrReachable
   747  	}
   748  	machogenasmsym(ctxt)
   749  	sortsym = make([]*sym.Symbol, nsortsym)
   750  	nsortsym = 0
   751  	machogenasmsym(ctxt)
   752  	sort.Sort(machoscmp(sortsym[:nsortsym]))
   753  	for i := 0; i < nsortsym; i++ {
   754  		sortsym[i].Dynid = int32(i)
   755  	}
   756  }
   757  
   758  // machoShouldExport reports whether a symbol needs to be exported.
   759  //
   760  // When dynamically linking, all non-local variables and plugin-exported
   761  // symbols need to be exported.
   762  func machoShouldExport(ctxt *Link, s *sym.Symbol) bool {
   763  	if !ctxt.DynlinkingGo() || s.Attr.Local() {
   764  		return false
   765  	}
   766  	if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(s.Extname, objabi.PathToPrefix(*flagPluginPath)) {
   767  		return true
   768  	}
   769  	if strings.HasPrefix(s.Name, "go.itab.") {
   770  		return true
   771  	}
   772  	if strings.HasPrefix(s.Name, "type.") && !strings.HasPrefix(s.Name, "type..") {
   773  		// reduce runtime typemap pressure, but do not
   774  		// export alg functions (type..*), as these
   775  		// appear in pclntable.
   776  		return true
   777  	}
   778  	if strings.HasPrefix(s.Name, "go.link.pkghash") {
   779  		return true
   780  	}
   781  	return s.Type >= sym.SELFSECT // only writable sections
   782  }
   783  
   784  func machosymtab(ctxt *Link) {
   785  	symtab := ctxt.Syms.Lookup(".machosymtab", 0)
   786  	symstr := ctxt.Syms.Lookup(".machosymstr", 0)
   787  
   788  	for i := 0; i < nsortsym; i++ {
   789  		s := sortsym[i]
   790  		symtab.AddUint32(ctxt.Arch, uint32(symstr.Size))
   791  
   792  		export := machoShouldExport(ctxt, s)
   793  
   794  		// In normal buildmodes, only add _ to C symbols, as
   795  		// Go symbols have dot in the name.
   796  		//
   797  		// Do not export C symbols in plugins, as runtime C
   798  		// symbols like crosscall2 are in pclntab and end up
   799  		// pointing at the host binary, breaking unwinding.
   800  		// See Issue #18190.
   801  		cexport := !strings.Contains(s.Extname, ".") && (ctxt.BuildMode != BuildModePlugin || onlycsymbol(s))
   802  		if cexport || export {
   803  			symstr.AddUint8('_')
   804  		}
   805  
   806  		// replace "·" as ".", because DTrace cannot handle it.
   807  		Addstring(symstr, strings.Replace(s.Extname, "·", ".", -1))
   808  
   809  		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
   810  			symtab.AddUint8(0x01)                             // type N_EXT, external symbol
   811  			symtab.AddUint8(0)                                // no section
   812  			symtab.AddUint16(ctxt.Arch, 0)                    // desc
   813  			symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value
   814  		} else {
   815  			if s.Attr.CgoExport() || export {
   816  				symtab.AddUint8(0x0f)
   817  			} else {
   818  				symtab.AddUint8(0x0e)
   819  			}
   820  			o := s
   821  			for o.Outer != nil {
   822  				o = o.Outer
   823  			}
   824  			if o.Sect == nil {
   825  				Errorf(s, "missing section for symbol")
   826  				symtab.AddUint8(0)
   827  			} else {
   828  				symtab.AddUint8(uint8(o.Sect.Extnum))
   829  			}
   830  			symtab.AddUint16(ctxt.Arch, 0) // desc
   831  			symtab.AddUintXX(ctxt.Arch, uint64(Symaddr(s)), ctxt.Arch.PtrSize)
   832  		}
   833  	}
   834  }
   835  
   836  func machodysymtab(ctxt *Link) {
   837  	ml := newMachoLoad(ctxt.Arch, LC_DYSYMTAB, 18)
   838  
   839  	n := 0
   840  	ml.data[0] = uint32(n)                   /* ilocalsym */
   841  	ml.data[1] = uint32(nkind[SymKindLocal]) /* nlocalsym */
   842  	n += nkind[SymKindLocal]
   843  
   844  	ml.data[2] = uint32(n)                    /* iextdefsym */
   845  	ml.data[3] = uint32(nkind[SymKindExtdef]) /* nextdefsym */
   846  	n += nkind[SymKindExtdef]
   847  
   848  	ml.data[4] = uint32(n)                   /* iundefsym */
   849  	ml.data[5] = uint32(nkind[SymKindUndef]) /* nundefsym */
   850  
   851  	ml.data[6] = 0  /* tocoffset */
   852  	ml.data[7] = 0  /* ntoc */
   853  	ml.data[8] = 0  /* modtaboff */
   854  	ml.data[9] = 0  /* nmodtab */
   855  	ml.data[10] = 0 /* extrefsymoff */
   856  	ml.data[11] = 0 /* nextrefsyms */
   857  
   858  	// must match domacholink below
   859  	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
   860  
   861  	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
   862  	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
   863  	ml.data[12] = uint32(linkoff + s1.Size)       /* indirectsymoff */
   864  	ml.data[13] = uint32((s2.Size + s3.Size) / 4) /* nindirectsyms */
   865  
   866  	ml.data[14] = 0 /* extreloff */
   867  	ml.data[15] = 0 /* nextrel */
   868  	ml.data[16] = 0 /* locreloff */
   869  	ml.data[17] = 0 /* nlocrel */
   870  }
   871  
   872  func Domacholink(ctxt *Link) int64 {
   873  	machosymtab(ctxt)
   874  
   875  	// write data that will be linkedit section
   876  	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
   877  
   878  	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
   879  	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
   880  	s4 := ctxt.Syms.Lookup(".machosymstr", 0)
   881  
   882  	// Force the linkedit section to end on a 16-byte
   883  	// boundary. This allows pure (non-cgo) Go binaries
   884  	// to be code signed correctly.
   885  	//
   886  	// Apple's codesign_allocate (a helper utility for
   887  	// the codesign utility) can do this fine itself if
   888  	// it is run on a dynamic Mach-O binary. However,
   889  	// when it is run on a pure (non-cgo) Go binary, where
   890  	// the linkedit section is mostly empty, it fails to
   891  	// account for the extra padding that it itself adds
   892  	// when adding the LC_CODE_SIGNATURE load command
   893  	// (which must be aligned on a 16-byte boundary).
   894  	//
   895  	// By forcing the linkedit section to end on a 16-byte
   896  	// boundary, codesign_allocate will not need to apply
   897  	// any alignment padding itself, working around the
   898  	// issue.
   899  	for s4.Size%16 != 0 {
   900  		s4.AddUint8(0)
   901  	}
   902  
   903  	size := int(s1.Size + s2.Size + s3.Size + s4.Size)
   904  
   905  	if size > 0 {
   906  		linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))
   907  		ctxt.Out.SeekSet(linkoff)
   908  
   909  		ctxt.Out.Write(s1.P[:s1.Size])
   910  		ctxt.Out.Write(s2.P[:s2.Size])
   911  		ctxt.Out.Write(s3.P[:s3.Size])
   912  		ctxt.Out.Write(s4.P[:s4.Size])
   913  	}
   914  
   915  	return Rnd(int64(size), int64(*FlagRound))
   916  }
   917  
   918  func machorelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
   919  	// If main section has no bits, nothing to relocate.
   920  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
   921  		return
   922  	}
   923  
   924  	sect.Reloff = uint64(ctxt.Out.Offset())
   925  	for i, s := range syms {
   926  		if !s.Attr.Reachable() {
   927  			continue
   928  		}
   929  		if uint64(s.Value) >= sect.Vaddr {
   930  			syms = syms[i:]
   931  			break
   932  		}
   933  	}
   934  
   935  	eaddr := int32(sect.Vaddr + sect.Length)
   936  	for _, s := range syms {
   937  		if !s.Attr.Reachable() {
   938  			continue
   939  		}
   940  		if s.Value >= int64(eaddr) {
   941  			break
   942  		}
   943  		for ri := 0; ri < len(s.R); ri++ {
   944  			r := &s.R[ri]
   945  			if r.Done {
   946  				continue
   947  			}
   948  			if r.Xsym == nil {
   949  				Errorf(s, "missing xsym in relocation")
   950  				continue
   951  			}
   952  			if !r.Xsym.Attr.Reachable() {
   953  				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
   954  			}
   955  			if !Thearch.Machoreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
   956  				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
   957  			}
   958  		}
   959  	}
   960  
   961  	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
   962  }
   963  
   964  func Machoemitreloc(ctxt *Link) {
   965  	for ctxt.Out.Offset()&7 != 0 {
   966  		ctxt.Out.Write8(0)
   967  	}
   968  
   969  	machorelocsect(ctxt, Segtext.Sections[0], ctxt.Textp)
   970  	for _, sect := range Segtext.Sections[1:] {
   971  		machorelocsect(ctxt, sect, datap)
   972  	}
   973  	for _, sect := range Segdata.Sections {
   974  		machorelocsect(ctxt, sect, datap)
   975  	}
   976  	for _, sect := range Segdwarf.Sections {
   977  		machorelocsect(ctxt, sect, dwarfp)
   978  	}
   979  }