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