github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/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 }