...
Run Format

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

Documentation: cmd/link/internal/ld

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ld
     6  
     7  import (
     8  	"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  		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 := range dynexp {
   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 := range s.R {
   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  }
   980  

View as plain text