github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/cmd/link/internal/amd64/asm.go (about) 1 // Inferno utils/6l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/asm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package amd64 32 33 import ( 34 "cmd/internal/obj" 35 "cmd/link/internal/ld" 36 "debug/elf" 37 "fmt" 38 "log" 39 ) 40 41 func PADDR(x uint32) uint32 { 42 return x &^ 0x80000000 43 } 44 45 func Addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) int64 { 46 s.Reachable = true 47 i := s.Size 48 s.Size += 4 49 ld.Symgrow(ctxt, s, s.Size) 50 r := ld.Addrel(s) 51 r.Sym = t 52 r.Off = int32(i) 53 r.Type = obj.R_CALL 54 r.Siz = 4 55 return i + int64(r.Siz) 56 } 57 58 func gentext() { 59 if !ld.DynlinkingGo() { 60 return 61 } 62 addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0) 63 if addmoduledata.Type == obj.STEXT { 64 // we're linking a module containing the runtime -> no need for 65 // an init function 66 return 67 } 68 addmoduledata.Reachable = true 69 initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0) 70 initfunc.Type = obj.STEXT 71 initfunc.Local = true 72 initfunc.Reachable = true 73 o := func(op ...uint8) { 74 for _, op1 := range op { 75 ld.Adduint8(ld.Ctxt, initfunc, op1) 76 } 77 } 78 // 0000000000000000 <local.dso_init>: 79 // 0: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 7 <local.dso_init+0x7> 80 // 3: R_X86_64_PC32 runtime.firstmoduledata-0x4 81 o(0x48, 0x8d, 0x3d) 82 ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Ctxt.Moduledata, 0) 83 // 7: e8 00 00 00 00 callq c <local.dso_init+0xc> 84 // 8: R_X86_64_PLT32 runtime.addmoduledata-0x4 85 o(0xe8) 86 Addcall(ld.Ctxt, initfunc, addmoduledata) 87 // c: c3 retq 88 o(0xc3) 89 if ld.Ctxt.Etextp != nil { 90 ld.Ctxt.Etextp.Next = initfunc 91 } else { 92 ld.Ctxt.Textp = initfunc 93 } 94 ld.Ctxt.Etextp = initfunc 95 initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0) 96 initarray_entry.Reachable = true 97 initarray_entry.Local = true 98 initarray_entry.Type = obj.SINITARR 99 ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) 100 } 101 102 func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { 103 ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off)) 104 ld.Adduint64(ld.Ctxt, rela, ld.R_X86_64_RELATIVE) 105 ld.Addaddrplus(ld.Ctxt, rela, r.Sym, r.Add) // Addend 106 } 107 108 func adddynrel(s *ld.LSym, r *ld.Reloc) { 109 targ := r.Sym 110 ld.Ctxt.Cursym = s 111 112 switch r.Type { 113 default: 114 if r.Type >= 256 { 115 ld.Diag("unexpected relocation type %d", r.Type) 116 return 117 } 118 119 // Handle relocations found in ELF object files. 120 case 256 + ld.R_X86_64_PC32: 121 if targ.Type == obj.SDYNIMPORT { 122 ld.Diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name) 123 } 124 if targ.Type == 0 || targ.Type == obj.SXREF { 125 ld.Diag("unknown symbol %s in pcrel", targ.Name) 126 } 127 r.Type = obj.R_PCREL 128 r.Add += 4 129 return 130 131 case 256 + ld.R_X86_64_PLT32: 132 r.Type = obj.R_PCREL 133 r.Add += 4 134 if targ.Type == obj.SDYNIMPORT { 135 addpltsym(targ) 136 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 137 r.Add += int64(targ.Plt) 138 } 139 140 return 141 142 case 256 + ld.R_X86_64_GOTPCREL: 143 if targ.Type != obj.SDYNIMPORT { 144 // have symbol 145 if r.Off >= 2 && s.P[r.Off-2] == 0x8b { 146 // turn MOVQ of GOT entry into LEAQ of symbol itself 147 s.P[r.Off-2] = 0x8d 148 149 r.Type = obj.R_PCREL 150 r.Add += 4 151 return 152 } 153 } 154 155 // fall back to using GOT and hope for the best (CMOV*) 156 // TODO: just needs relocation, no need to put in .dynsym 157 addgotsym(targ) 158 159 r.Type = obj.R_PCREL 160 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 161 r.Add += 4 162 r.Add += int64(targ.Got) 163 return 164 165 case 256 + ld.R_X86_64_64: 166 if targ.Type == obj.SDYNIMPORT { 167 ld.Diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name) 168 } 169 r.Type = obj.R_ADDR 170 return 171 172 // Handle relocations found in Mach-O object files. 173 case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0, 174 512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0, 175 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0: 176 // TODO: What is the difference between all these? 177 r.Type = obj.R_ADDR 178 179 if targ.Type == obj.SDYNIMPORT { 180 ld.Diag("unexpected reloc for dynamic symbol %s", targ.Name) 181 } 182 return 183 184 case 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1: 185 if targ.Type == obj.SDYNIMPORT { 186 addpltsym(targ) 187 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 188 r.Add = int64(targ.Plt) 189 r.Type = obj.R_PCREL 190 return 191 } 192 fallthrough 193 194 // fall through 195 case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1, 196 512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1, 197 512 + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1, 198 512 + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1, 199 512 + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1: 200 r.Type = obj.R_PCREL 201 202 if targ.Type == obj.SDYNIMPORT { 203 ld.Diag("unexpected pc-relative reloc for dynamic symbol %s", targ.Name) 204 } 205 return 206 207 case 512 + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1: 208 if targ.Type != obj.SDYNIMPORT { 209 // have symbol 210 // turn MOVQ of GOT entry into LEAQ of symbol itself 211 if r.Off < 2 || s.P[r.Off-2] != 0x8b { 212 ld.Diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ.Name) 213 return 214 } 215 216 s.P[r.Off-2] = 0x8d 217 r.Type = obj.R_PCREL 218 return 219 } 220 fallthrough 221 222 // fall through 223 case 512 + ld.MACHO_X86_64_RELOC_GOT*2 + 1: 224 if targ.Type != obj.SDYNIMPORT { 225 ld.Diag("unexpected GOT reloc for non-dynamic symbol %s", targ.Name) 226 } 227 addgotsym(targ) 228 r.Type = obj.R_PCREL 229 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 230 r.Add += int64(targ.Got) 231 return 232 } 233 234 // Handle references to ELF symbols from our own object files. 235 if targ.Type != obj.SDYNIMPORT { 236 return 237 } 238 239 switch r.Type { 240 case obj.R_CALL, 241 obj.R_PCREL: 242 if ld.HEADTYPE == obj.Hwindows { 243 // nothing to do, the relocation will be laid out in pereloc1 244 return 245 } else { 246 // for both ELF and Mach-O 247 addpltsym(targ) 248 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 249 r.Add = int64(targ.Plt) 250 return 251 } 252 253 case obj.R_ADDR: 254 if s.Type == obj.STEXT && ld.Iself { 255 if ld.HEADTYPE == obj.Hsolaris { 256 addpltsym(targ) 257 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 258 r.Add += int64(targ.Plt) 259 return 260 } 261 // The code is asking for the address of an external 262 // function. We provide it with the address of the 263 // correspondent GOT symbol. 264 addgotsym(targ) 265 266 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 267 r.Add += int64(targ.Got) 268 return 269 } 270 271 if s.Type != obj.SDATA { 272 break 273 } 274 if ld.Iself { 275 ld.Adddynsym(ld.Ctxt, targ) 276 rela := ld.Linklookup(ld.Ctxt, ".rela", 0) 277 ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off)) 278 if r.Siz == 8 { 279 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_X86_64_64)) 280 } else { 281 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_X86_64_32)) 282 } 283 ld.Adduint64(ld.Ctxt, rela, uint64(r.Add)) 284 r.Type = 256 // ignore during relocsym 285 return 286 } 287 288 if ld.HEADTYPE == obj.Hdarwin && s.Size == int64(ld.Thearch.Ptrsize) && r.Off == 0 { 289 // Mach-O relocations are a royal pain to lay out. 290 // They use a compact stateful bytecode representation 291 // that is too much bother to deal with. 292 // Instead, interpret the C declaration 293 // void *_Cvar_stderr = &stderr; 294 // as making _Cvar_stderr the name of a GOT entry 295 // for stderr. This is separate from the usual GOT entry, 296 // just in case the C code assigns to the variable, 297 // and of course it only works for single pointers, 298 // but we only need to support cgo and that's all it needs. 299 ld.Adddynsym(ld.Ctxt, targ) 300 301 got := ld.Linklookup(ld.Ctxt, ".got", 0) 302 s.Type = got.Type | obj.SSUB 303 s.Outer = got 304 s.Sub = got.Sub 305 got.Sub = s 306 s.Value = got.Size 307 ld.Adduint64(ld.Ctxt, got, 0) 308 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.got", 0), uint32(targ.Dynid)) 309 r.Type = 256 // ignore during relocsym 310 return 311 } 312 313 if ld.HEADTYPE == obj.Hwindows { 314 // nothing to do, the relocation will be laid out in pereloc1 315 return 316 } 317 } 318 319 ld.Ctxt.Cursym = s 320 ld.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type) 321 } 322 323 func elfreloc1(r *ld.Reloc, sectoff int64) int { 324 ld.Thearch.Vput(uint64(sectoff)) 325 326 elfsym := r.Xsym.Elfsym 327 switch r.Type { 328 default: 329 return -1 330 331 case obj.R_ADDR: 332 if r.Siz == 4 { 333 ld.Thearch.Vput(ld.R_X86_64_32 | uint64(elfsym)<<32) 334 } else if r.Siz == 8 { 335 ld.Thearch.Vput(ld.R_X86_64_64 | uint64(elfsym)<<32) 336 } else { 337 return -1 338 } 339 340 case obj.R_TLS_LE: 341 if r.Siz == 4 { 342 ld.Thearch.Vput(ld.R_X86_64_TPOFF32 | uint64(elfsym)<<32) 343 } else { 344 return -1 345 } 346 347 case obj.R_TLS_IE: 348 if r.Siz == 4 { 349 ld.Thearch.Vput(ld.R_X86_64_GOTTPOFF | uint64(elfsym)<<32) 350 } else { 351 return -1 352 } 353 354 case obj.R_CALL: 355 if r.Siz == 4 { 356 if r.Xsym.Type == obj.SDYNIMPORT { 357 if ld.DynlinkingGo() { 358 ld.Thearch.Vput(ld.R_X86_64_PLT32 | uint64(elfsym)<<32) 359 } else { 360 ld.Thearch.Vput(ld.R_X86_64_GOTPCREL | uint64(elfsym)<<32) 361 } 362 } else { 363 ld.Thearch.Vput(ld.R_X86_64_PC32 | uint64(elfsym)<<32) 364 } 365 } else { 366 return -1 367 } 368 369 case obj.R_PCREL: 370 if r.Siz == 4 { 371 if r.Xsym.Type == obj.SDYNIMPORT && r.Xsym.ElfType == elf.STT_FUNC { 372 ld.Thearch.Vput(ld.R_X86_64_PLT32 | uint64(elfsym)<<32) 373 } else { 374 ld.Thearch.Vput(ld.R_X86_64_PC32 | uint64(elfsym)<<32) 375 } 376 } else { 377 return -1 378 } 379 380 case obj.R_GOTPCREL: 381 if r.Siz == 4 { 382 ld.Thearch.Vput(ld.R_X86_64_GOTPCREL | uint64(elfsym)<<32) 383 } else { 384 return -1 385 } 386 } 387 388 ld.Thearch.Vput(uint64(r.Xadd)) 389 return 0 390 } 391 392 func machoreloc1(r *ld.Reloc, sectoff int64) int { 393 var v uint32 394 395 rs := r.Xsym 396 397 if rs.Type == obj.SHOSTOBJ || r.Type == obj.R_PCREL { 398 if rs.Dynid < 0 { 399 ld.Diag("reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type) 400 return -1 401 } 402 403 v = uint32(rs.Dynid) 404 v |= 1 << 27 // external relocation 405 } else { 406 v = uint32(rs.Sect.Extnum) 407 if v == 0 { 408 ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type) 409 return -1 410 } 411 } 412 413 switch r.Type { 414 default: 415 return -1 416 417 case obj.R_ADDR: 418 v |= ld.MACHO_X86_64_RELOC_UNSIGNED << 28 419 420 case obj.R_CALL: 421 v |= 1 << 24 // pc-relative bit 422 v |= ld.MACHO_X86_64_RELOC_BRANCH << 28 423 424 // NOTE: Only works with 'external' relocation. Forced above. 425 case obj.R_PCREL: 426 v |= 1 << 24 // pc-relative bit 427 v |= ld.MACHO_X86_64_RELOC_SIGNED << 28 428 } 429 430 switch r.Siz { 431 default: 432 return -1 433 434 case 1: 435 v |= 0 << 25 436 437 case 2: 438 v |= 1 << 25 439 440 case 4: 441 v |= 2 << 25 442 443 case 8: 444 v |= 3 << 25 445 } 446 447 ld.Thearch.Lput(uint32(sectoff)) 448 ld.Thearch.Lput(v) 449 return 0 450 } 451 452 func pereloc1(r *ld.Reloc, sectoff int64) bool { 453 var v uint32 454 455 rs := r.Xsym 456 457 if rs.Dynid < 0 { 458 ld.Diag("reloc %d to non-coff symbol %s type=%d", r.Type, rs.Name, rs.Type) 459 return false 460 } 461 462 ld.Thearch.Lput(uint32(sectoff)) 463 ld.Thearch.Lput(uint32(rs.Dynid)) 464 465 switch r.Type { 466 default: 467 return false 468 469 case obj.R_ADDR: 470 if r.Siz == 8 { 471 v = ld.IMAGE_REL_AMD64_ADDR64 472 } else { 473 v = ld.IMAGE_REL_AMD64_ADDR32 474 } 475 476 case obj.R_CALL, 477 obj.R_PCREL: 478 v = ld.IMAGE_REL_AMD64_REL32 479 } 480 481 ld.Thearch.Wput(uint16(v)) 482 483 return true 484 } 485 486 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { 487 return -1 488 } 489 490 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 { 491 log.Fatalf("unexpected relocation variant") 492 return t 493 } 494 495 func elfsetupplt() { 496 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 497 got := ld.Linklookup(ld.Ctxt, ".got.plt", 0) 498 if plt.Size == 0 { 499 // pushq got+8(IP) 500 ld.Adduint8(ld.Ctxt, plt, 0xff) 501 502 ld.Adduint8(ld.Ctxt, plt, 0x35) 503 ld.Addpcrelplus(ld.Ctxt, plt, got, 8) 504 505 // jmpq got+16(IP) 506 ld.Adduint8(ld.Ctxt, plt, 0xff) 507 508 ld.Adduint8(ld.Ctxt, plt, 0x25) 509 ld.Addpcrelplus(ld.Ctxt, plt, got, 16) 510 511 // nopl 0(AX) 512 ld.Adduint32(ld.Ctxt, plt, 0x00401f0f) 513 514 // assume got->size == 0 too 515 ld.Addaddrplus(ld.Ctxt, got, ld.Linklookup(ld.Ctxt, ".dynamic", 0), 0) 516 517 ld.Adduint64(ld.Ctxt, got, 0) 518 ld.Adduint64(ld.Ctxt, got, 0) 519 } 520 } 521 522 func addpltsym(s *ld.LSym) { 523 if s.Plt >= 0 { 524 return 525 } 526 527 ld.Adddynsym(ld.Ctxt, s) 528 529 if ld.Iself { 530 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 531 got := ld.Linklookup(ld.Ctxt, ".got.plt", 0) 532 rela := ld.Linklookup(ld.Ctxt, ".rela.plt", 0) 533 if plt.Size == 0 { 534 elfsetupplt() 535 } 536 537 // jmpq *got+size(IP) 538 ld.Adduint8(ld.Ctxt, plt, 0xff) 539 540 ld.Adduint8(ld.Ctxt, plt, 0x25) 541 ld.Addpcrelplus(ld.Ctxt, plt, got, got.Size) 542 543 // add to got: pointer to current pos in plt 544 ld.Addaddrplus(ld.Ctxt, got, plt, plt.Size) 545 546 // pushq $x 547 ld.Adduint8(ld.Ctxt, plt, 0x68) 548 549 ld.Adduint32(ld.Ctxt, plt, uint32((got.Size-24-8)/8)) 550 551 // jmpq .plt 552 ld.Adduint8(ld.Ctxt, plt, 0xe9) 553 554 ld.Adduint32(ld.Ctxt, plt, uint32(-(plt.Size + 4))) 555 556 // rela 557 ld.Addaddrplus(ld.Ctxt, rela, got, got.Size-8) 558 559 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_X86_64_JMP_SLOT)) 560 ld.Adduint64(ld.Ctxt, rela, 0) 561 562 s.Plt = int32(plt.Size - 16) 563 } else if ld.HEADTYPE == obj.Hdarwin { 564 // To do lazy symbol lookup right, we're supposed 565 // to tell the dynamic loader which library each 566 // symbol comes from and format the link info 567 // section just so. I'm too lazy (ha!) to do that 568 // so for now we'll just use non-lazy pointers, 569 // which don't need to be told which library to use. 570 // 571 // http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html 572 // has details about what we're avoiding. 573 574 addgotsym(s) 575 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 576 577 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.plt", 0), uint32(s.Dynid)) 578 579 // jmpq *got+size(IP) 580 s.Plt = int32(plt.Size) 581 582 ld.Adduint8(ld.Ctxt, plt, 0xff) 583 ld.Adduint8(ld.Ctxt, plt, 0x25) 584 ld.Addpcrelplus(ld.Ctxt, plt, ld.Linklookup(ld.Ctxt, ".got", 0), int64(s.Got)) 585 } else { 586 ld.Diag("addpltsym: unsupported binary format") 587 } 588 } 589 590 func addgotsym(s *ld.LSym) { 591 if s.Got >= 0 { 592 return 593 } 594 595 ld.Adddynsym(ld.Ctxt, s) 596 got := ld.Linklookup(ld.Ctxt, ".got", 0) 597 s.Got = int32(got.Size) 598 ld.Adduint64(ld.Ctxt, got, 0) 599 600 if ld.Iself { 601 rela := ld.Linklookup(ld.Ctxt, ".rela", 0) 602 ld.Addaddrplus(ld.Ctxt, rela, got, int64(s.Got)) 603 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_X86_64_GLOB_DAT)) 604 ld.Adduint64(ld.Ctxt, rela, 0) 605 } else if ld.HEADTYPE == obj.Hdarwin { 606 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.got", 0), uint32(s.Dynid)) 607 } else { 608 ld.Diag("addgotsym: unsupported binary format") 609 } 610 } 611 612 func asmb() { 613 if ld.Debug['v'] != 0 { 614 fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime()) 615 } 616 ld.Bso.Flush() 617 618 if ld.Debug['v'] != 0 { 619 fmt.Fprintf(&ld.Bso, "%5.2f codeblk\n", obj.Cputime()) 620 } 621 ld.Bso.Flush() 622 623 if ld.Iself { 624 ld.Asmbelfsetup() 625 } 626 627 sect := ld.Segtext.Sect 628 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 629 ld.Codeblk(int64(sect.Vaddr), int64(sect.Length)) 630 for sect = sect.Next; sect != nil; sect = sect.Next { 631 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 632 ld.Datblk(int64(sect.Vaddr), int64(sect.Length)) 633 } 634 635 if ld.Segrodata.Filelen > 0 { 636 if ld.Debug['v'] != 0 { 637 fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime()) 638 } 639 ld.Bso.Flush() 640 641 ld.Cseek(int64(ld.Segrodata.Fileoff)) 642 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 643 } 644 645 if ld.Debug['v'] != 0 { 646 fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime()) 647 } 648 ld.Bso.Flush() 649 650 ld.Cseek(int64(ld.Segdata.Fileoff)) 651 ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 652 653 machlink := int64(0) 654 if ld.HEADTYPE == obj.Hdarwin { 655 if ld.Debug['v'] != 0 { 656 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 657 } 658 659 dwarfoff := ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) 660 ld.Cseek(dwarfoff) 661 662 ld.Segdwarf.Fileoff = uint64(ld.Cpos()) 663 ld.Dwarfemitdebugsections() 664 ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff 665 666 machlink = ld.Domacholink() 667 } 668 669 switch ld.HEADTYPE { 670 default: 671 ld.Diag("unknown header type %d", ld.HEADTYPE) 672 fallthrough 673 674 case obj.Hplan9, 675 obj.Helf: 676 break 677 678 case obj.Hdarwin: 679 ld.Debug['8'] = 1 /* 64-bit addresses */ 680 681 case obj.Hlinux, 682 obj.Hfreebsd, 683 obj.Hnetbsd, 684 obj.Hopenbsd, 685 obj.Hdragonfly, 686 obj.Hsolaris: 687 ld.Debug['8'] = 1 /* 64-bit addresses */ 688 689 case obj.Hnacl, 690 obj.Hwindows: 691 break 692 } 693 694 ld.Symsize = 0 695 ld.Spsize = 0 696 ld.Lcsize = 0 697 symo := int64(0) 698 if ld.Debug['s'] == 0 { 699 if ld.Debug['v'] != 0 { 700 fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime()) 701 } 702 ld.Bso.Flush() 703 switch ld.HEADTYPE { 704 default: 705 case obj.Hplan9, 706 obj.Helf: 707 ld.Debug['s'] = 1 708 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) 709 710 case obj.Hdarwin: 711 symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink)) 712 713 case obj.Hlinux, 714 obj.Hfreebsd, 715 obj.Hnetbsd, 716 obj.Hopenbsd, 717 obj.Hdragonfly, 718 obj.Hsolaris, 719 obj.Hnacl: 720 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) 721 symo = ld.Rnd(symo, int64(ld.INITRND)) 722 723 case obj.Hwindows: 724 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) 725 symo = ld.Rnd(symo, ld.PEFILEALIGN) 726 } 727 728 ld.Cseek(symo) 729 switch ld.HEADTYPE { 730 default: 731 if ld.Iself { 732 ld.Cseek(symo) 733 ld.Asmelfsym() 734 ld.Cflush() 735 ld.Cwrite(ld.Elfstrdat) 736 737 if ld.Debug['v'] != 0 { 738 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 739 } 740 741 ld.Dwarfemitdebugsections() 742 743 if ld.Linkmode == ld.LinkExternal { 744 ld.Elfemitreloc() 745 } 746 } 747 748 case obj.Hplan9: 749 ld.Asmplan9sym() 750 ld.Cflush() 751 752 sym := ld.Linklookup(ld.Ctxt, "pclntab", 0) 753 if sym != nil { 754 ld.Lcsize = int32(len(sym.P)) 755 for i := 0; int32(i) < ld.Lcsize; i++ { 756 ld.Cput(uint8(sym.P[i])) 757 } 758 759 ld.Cflush() 760 } 761 762 case obj.Hwindows: 763 if ld.Debug['v'] != 0 { 764 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 765 } 766 767 ld.Dwarfemitdebugsections() 768 769 case obj.Hdarwin: 770 if ld.Linkmode == ld.LinkExternal { 771 ld.Machoemitreloc() 772 } 773 } 774 } 775 776 if ld.Debug['v'] != 0 { 777 fmt.Fprintf(&ld.Bso, "%5.2f headr\n", obj.Cputime()) 778 } 779 ld.Bso.Flush() 780 ld.Cseek(0) 781 switch ld.HEADTYPE { 782 default: 783 case obj.Hplan9: /* plan9 */ 784 magic := int32(4*26*26 + 7) 785 786 magic |= 0x00008000 /* fat header */ 787 ld.Lputb(uint32(magic)) /* magic */ 788 ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */ 789 ld.Lputb(uint32(ld.Segdata.Filelen)) 790 ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 791 ld.Lputb(uint32(ld.Symsize)) /* nsyms */ 792 vl := ld.Entryvalue() 793 ld.Lputb(PADDR(uint32(vl))) /* va of entry */ 794 ld.Lputb(uint32(ld.Spsize)) /* sp offsets */ 795 ld.Lputb(uint32(ld.Lcsize)) /* line offsets */ 796 ld.Vputb(uint64(vl)) /* va of entry */ 797 798 case obj.Hdarwin: 799 ld.Asmbmacho() 800 801 case obj.Hlinux, 802 obj.Hfreebsd, 803 obj.Hnetbsd, 804 obj.Hopenbsd, 805 obj.Hdragonfly, 806 obj.Hsolaris, 807 obj.Hnacl: 808 ld.Asmbelf(symo) 809 810 case obj.Hwindows: 811 ld.Asmbpe() 812 } 813 814 ld.Cflush() 815 }