github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/cmd/link/internal/x86/asm.go (about) 1 // Inferno utils/8l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/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 x86 32 33 import ( 34 "cmd/internal/obj" 35 "cmd/link/internal/ld" 36 "fmt" 37 "log" 38 ) 39 40 // Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in. 41 func addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) { 42 s.Reachable = true 43 i := s.Size 44 s.Size += 4 45 ld.Symgrow(ctxt, s, s.Size) 46 r := ld.Addrel(s) 47 r.Sym = t 48 r.Off = int32(i) 49 r.Type = obj.R_CALL 50 r.Siz = 4 51 } 52 53 func gentext() { 54 if !ld.DynlinkingGo() && ld.Buildmode != ld.BuildmodePIE && ld.Buildmode != ld.BuildmodeCShared { 55 return 56 } 57 58 thunkfunc := ld.Linklookup(ld.Ctxt, "__x86.get_pc_thunk.cx", 0) 59 thunkfunc.Type = obj.STEXT 60 thunkfunc.Local = true 61 thunkfunc.Reachable = true 62 o := func(op ...uint8) { 63 for _, op1 := range op { 64 ld.Adduint8(ld.Ctxt, thunkfunc, op1) 65 } 66 } 67 // 8b 0c 24 mov (%esp),%ecx 68 o(0x8b, 0x0c, 0x24) 69 // c3 ret 70 o(0xc3) 71 72 if ld.Ctxt.Etextp != nil { 73 ld.Ctxt.Etextp.Next = thunkfunc 74 } else { 75 ld.Ctxt.Textp = thunkfunc 76 } 77 ld.Ctxt.Etextp = thunkfunc 78 79 addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0) 80 if addmoduledata.Type == obj.STEXT { 81 // we're linking a module containing the runtime -> no need for 82 // an init function 83 return 84 } 85 86 addmoduledata.Reachable = true 87 88 initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0) 89 initfunc.Type = obj.STEXT 90 initfunc.Local = true 91 initfunc.Reachable = true 92 o = func(op ...uint8) { 93 for _, op1 := range op { 94 ld.Adduint8(ld.Ctxt, initfunc, op1) 95 } 96 } 97 98 // go.link.addmoduledata: 99 // 53 push %ebx 100 // e8 00 00 00 00 call __x86.get_pc_thunk.cx + R_CALL __x86.get_pc_thunk.cx 101 // 8d 81 00 00 00 00 lea 0x0(%ecx), %eax + R_PCREL ld.Ctxt.Moduledata 102 // 8d 99 00 00 00 00 lea 0x0(%ecx), %ebx + R_GOTPC _GLOBAL_OFFSET_TABLE_ 103 // e8 00 00 00 00 call runtime.addmoduledata@plt + R_CALL runtime.addmoduledata 104 // 5b pop %ebx 105 // c3 ret 106 107 o(0x53) 108 109 o(0xe8) 110 addcall(ld.Ctxt, initfunc, ld.Linklookup(ld.Ctxt, "__x86.get_pc_thunk.cx", 0)) 111 112 o(0x8d, 0x81) 113 ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Ctxt.Moduledata, 6) 114 115 o(0x8d, 0x99) 116 i := initfunc.Size 117 initfunc.Size += 4 118 ld.Symgrow(ld.Ctxt, initfunc, initfunc.Size) 119 r := ld.Addrel(initfunc) 120 r.Sym = ld.Linklookup(ld.Ctxt, "_GLOBAL_OFFSET_TABLE_", 0) 121 r.Off = int32(i) 122 r.Type = obj.R_PCREL 123 r.Add = 12 124 r.Siz = 4 125 126 o(0xe8) 127 addcall(ld.Ctxt, initfunc, addmoduledata) 128 129 o(0x5b) 130 131 o(0xc3) 132 133 ld.Ctxt.Etextp.Next = initfunc 134 ld.Ctxt.Etextp = initfunc 135 initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0) 136 initarray_entry.Reachable = true 137 initarray_entry.Local = true 138 initarray_entry.Type = obj.SINITARR 139 ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) 140 } 141 142 func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { 143 log.Fatalf("adddynrela not implemented") 144 } 145 146 func adddynrel(s *ld.LSym, r *ld.Reloc) { 147 targ := r.Sym 148 ld.Ctxt.Cursym = s 149 150 switch r.Type { 151 default: 152 if r.Type >= 256 { 153 ld.Diag("unexpected relocation type %d", r.Type) 154 return 155 } 156 157 // Handle relocations found in ELF object files. 158 case 256 + ld.R_386_PC32: 159 if targ.Type == obj.SDYNIMPORT { 160 ld.Diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name) 161 } 162 if targ.Type == 0 || targ.Type == obj.SXREF { 163 ld.Diag("unknown symbol %s in pcrel", targ.Name) 164 } 165 r.Type = obj.R_PCREL 166 r.Add += 4 167 return 168 169 case 256 + ld.R_386_PLT32: 170 r.Type = obj.R_PCREL 171 r.Add += 4 172 if targ.Type == obj.SDYNIMPORT { 173 addpltsym(ld.Ctxt, targ) 174 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 175 r.Add += int64(targ.Plt) 176 } 177 178 return 179 180 case 256 + ld.R_386_GOT32, 256 + ld.R_386_GOT32X: 181 if targ.Type != obj.SDYNIMPORT { 182 // have symbol 183 if r.Off >= 2 && s.P[r.Off-2] == 0x8b { 184 // turn MOVL of GOT entry into LEAL of symbol address, relative to GOT. 185 s.P[r.Off-2] = 0x8d 186 187 r.Type = obj.R_GOTOFF 188 return 189 } 190 191 if r.Off >= 2 && s.P[r.Off-2] == 0xff && s.P[r.Off-1] == 0xb3 { 192 // turn PUSHL of GOT entry into PUSHL of symbol itself. 193 // use unnecessary SS prefix to keep instruction same length. 194 s.P[r.Off-2] = 0x36 195 196 s.P[r.Off-1] = 0x68 197 r.Type = obj.R_ADDR 198 return 199 } 200 201 ld.Diag("unexpected GOT reloc for non-dynamic symbol %s", targ.Name) 202 return 203 } 204 205 addgotsym(ld.Ctxt, targ) 206 r.Type = obj.R_CONST // write r->add during relocsym 207 r.Sym = nil 208 r.Add += int64(targ.Got) 209 return 210 211 case 256 + ld.R_386_GOTOFF: 212 r.Type = obj.R_GOTOFF 213 return 214 215 case 256 + ld.R_386_GOTPC: 216 r.Type = obj.R_PCREL 217 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 218 r.Add += 4 219 return 220 221 case 256 + ld.R_386_32: 222 if targ.Type == obj.SDYNIMPORT { 223 ld.Diag("unexpected R_386_32 relocation for dynamic symbol %s", targ.Name) 224 } 225 r.Type = obj.R_ADDR 226 return 227 228 case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0: 229 r.Type = obj.R_ADDR 230 if targ.Type == obj.SDYNIMPORT { 231 ld.Diag("unexpected reloc for dynamic symbol %s", targ.Name) 232 } 233 return 234 235 case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1: 236 if targ.Type == obj.SDYNIMPORT { 237 addpltsym(ld.Ctxt, targ) 238 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 239 r.Add = int64(targ.Plt) 240 r.Type = obj.R_PCREL 241 return 242 } 243 244 r.Type = obj.R_PCREL 245 return 246 247 case 512 + ld.MACHO_FAKE_GOTPCREL: 248 if targ.Type != obj.SDYNIMPORT { 249 // have symbol 250 // turn MOVL of GOT entry into LEAL of symbol itself 251 if r.Off < 2 || s.P[r.Off-2] != 0x8b { 252 ld.Diag("unexpected GOT reloc for non-dynamic symbol %s", targ.Name) 253 return 254 } 255 256 s.P[r.Off-2] = 0x8d 257 r.Type = obj.R_PCREL 258 return 259 } 260 261 addgotsym(ld.Ctxt, targ) 262 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 263 r.Add += int64(targ.Got) 264 r.Type = obj.R_PCREL 265 return 266 } 267 268 // Handle references to ELF symbols from our own object files. 269 if targ.Type != obj.SDYNIMPORT { 270 return 271 } 272 273 switch r.Type { 274 case obj.R_CALL, 275 obj.R_PCREL: 276 addpltsym(ld.Ctxt, targ) 277 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 278 r.Add = int64(targ.Plt) 279 return 280 281 case obj.R_ADDR: 282 if s.Type != obj.SDATA { 283 break 284 } 285 if ld.Iself { 286 ld.Adddynsym(ld.Ctxt, targ) 287 rel := ld.Linklookup(ld.Ctxt, ".rel", 0) 288 ld.Addaddrplus(ld.Ctxt, rel, s, int64(r.Off)) 289 ld.Adduint32(ld.Ctxt, rel, ld.ELF32_R_INFO(uint32(targ.Dynid), ld.R_386_32)) 290 r.Type = obj.R_CONST // write r->add during relocsym 291 r.Sym = nil 292 return 293 } 294 295 if ld.HEADTYPE == obj.Hdarwin && s.Size == PtrSize && r.Off == 0 { 296 // Mach-O relocations are a royal pain to lay out. 297 // They use a compact stateful bytecode representation 298 // that is too much bother to deal with. 299 // Instead, interpret the C declaration 300 // void *_Cvar_stderr = &stderr; 301 // as making _Cvar_stderr the name of a GOT entry 302 // for stderr. This is separate from the usual GOT entry, 303 // just in case the C code assigns to the variable, 304 // and of course it only works for single pointers, 305 // but we only need to support cgo and that's all it needs. 306 ld.Adddynsym(ld.Ctxt, targ) 307 308 got := ld.Linklookup(ld.Ctxt, ".got", 0) 309 s.Type = got.Type | obj.SSUB 310 s.Outer = got 311 s.Sub = got.Sub 312 got.Sub = s 313 s.Value = got.Size 314 ld.Adduint32(ld.Ctxt, got, 0) 315 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.got", 0), uint32(targ.Dynid)) 316 r.Type = 256 // ignore during relocsym 317 return 318 } 319 320 if ld.HEADTYPE == obj.Hwindows && s.Size == PtrSize { 321 // nothing to do, the relocation will be laid out in pereloc1 322 return 323 } 324 } 325 326 ld.Ctxt.Cursym = s 327 ld.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type) 328 } 329 330 func elfreloc1(r *ld.Reloc, sectoff int64) int { 331 ld.Thearch.Lput(uint32(sectoff)) 332 333 elfsym := r.Xsym.ElfsymForReloc() 334 switch r.Type { 335 default: 336 return -1 337 338 case obj.R_ADDR: 339 if r.Siz == 4 { 340 ld.Thearch.Lput(ld.R_386_32 | uint32(elfsym)<<8) 341 } else { 342 return -1 343 } 344 345 case obj.R_GOTPCREL: 346 if r.Siz == 4 { 347 ld.Thearch.Lput(ld.R_386_GOTPC) 348 if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" { 349 ld.Thearch.Lput(uint32(sectoff)) 350 ld.Thearch.Lput(ld.R_386_GOT32 | uint32(elfsym)<<8) 351 } 352 } else { 353 return -1 354 } 355 356 case obj.R_CALL: 357 if r.Siz == 4 { 358 if r.Xsym.Type == obj.SDYNIMPORT { 359 ld.Thearch.Lput(ld.R_386_PLT32 | uint32(elfsym)<<8) 360 } else { 361 ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8) 362 } 363 } else { 364 return -1 365 } 366 367 case obj.R_PCREL: 368 if r.Siz == 4 { 369 ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8) 370 } else { 371 return -1 372 } 373 374 case obj.R_TLS_LE: 375 if r.Siz == 4 { 376 ld.Thearch.Lput(ld.R_386_TLS_LE | uint32(elfsym)<<8) 377 } else { 378 return -1 379 } 380 381 case obj.R_TLS_IE: 382 if r.Siz == 4 { 383 ld.Thearch.Lput(ld.R_386_GOTPC) 384 ld.Thearch.Lput(uint32(sectoff)) 385 ld.Thearch.Lput(ld.R_386_TLS_GOTIE | uint32(elfsym)<<8) 386 } else { 387 return -1 388 } 389 } 390 391 return 0 392 } 393 394 func machoreloc1(r *ld.Reloc, sectoff int64) int { 395 var v uint32 396 397 rs := r.Xsym 398 399 if rs.Type == obj.SHOSTOBJ { 400 if rs.Dynid < 0 { 401 ld.Diag("reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type) 402 return -1 403 } 404 405 v = uint32(rs.Dynid) 406 v |= 1 << 27 // external relocation 407 } else { 408 v = uint32(rs.Sect.Extnum) 409 if v == 0 { 410 ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type) 411 return -1 412 } 413 } 414 415 switch r.Type { 416 default: 417 return -1 418 419 case obj.R_ADDR: 420 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 421 422 case obj.R_CALL, 423 obj.R_PCREL: 424 v |= 1 << 24 // pc-relative bit 425 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 426 } 427 428 switch r.Siz { 429 default: 430 return -1 431 432 case 1: 433 v |= 0 << 25 434 435 case 2: 436 v |= 1 << 25 437 438 case 4: 439 v |= 2 << 25 440 441 case 8: 442 v |= 3 << 25 443 } 444 445 ld.Thearch.Lput(uint32(sectoff)) 446 ld.Thearch.Lput(v) 447 return 0 448 } 449 450 func pereloc1(r *ld.Reloc, sectoff int64) bool { 451 var v uint32 452 453 rs := r.Xsym 454 455 if rs.Dynid < 0 { 456 ld.Diag("reloc %d to non-coff symbol %s type=%d", r.Type, rs.Name, rs.Type) 457 return false 458 } 459 460 ld.Thearch.Lput(uint32(sectoff)) 461 ld.Thearch.Lput(uint32(rs.Dynid)) 462 463 switch r.Type { 464 default: 465 return false 466 467 case obj.R_ADDR: 468 v = ld.IMAGE_REL_I386_DIR32 469 470 case obj.R_CALL, 471 obj.R_PCREL: 472 v = ld.IMAGE_REL_I386_REL32 473 } 474 475 ld.Thearch.Wput(uint16(v)) 476 477 return true 478 } 479 480 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { 481 if ld.Linkmode == ld.LinkExternal { 482 return -1 483 } 484 switch r.Type { 485 case obj.R_CONST: 486 *val = r.Add 487 return 0 488 489 case obj.R_GOTOFF: 490 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0)) 491 return 0 492 } 493 494 return -1 495 } 496 497 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 { 498 log.Fatalf("unexpected relocation variant") 499 return t 500 } 501 502 func elfsetupplt() { 503 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 504 got := ld.Linklookup(ld.Ctxt, ".got.plt", 0) 505 if plt.Size == 0 { 506 // pushl got+4 507 ld.Adduint8(ld.Ctxt, plt, 0xff) 508 509 ld.Adduint8(ld.Ctxt, plt, 0x35) 510 ld.Addaddrplus(ld.Ctxt, plt, got, 4) 511 512 // jmp *got+8 513 ld.Adduint8(ld.Ctxt, plt, 0xff) 514 515 ld.Adduint8(ld.Ctxt, plt, 0x25) 516 ld.Addaddrplus(ld.Ctxt, plt, got, 8) 517 518 // zero pad 519 ld.Adduint32(ld.Ctxt, plt, 0) 520 521 // assume got->size == 0 too 522 ld.Addaddrplus(ld.Ctxt, got, ld.Linklookup(ld.Ctxt, ".dynamic", 0), 0) 523 524 ld.Adduint32(ld.Ctxt, got, 0) 525 ld.Adduint32(ld.Ctxt, got, 0) 526 } 527 } 528 529 func addpltsym(ctxt *ld.Link, s *ld.LSym) { 530 if s.Plt >= 0 { 531 return 532 } 533 534 ld.Adddynsym(ctxt, s) 535 536 if ld.Iself { 537 plt := ld.Linklookup(ctxt, ".plt", 0) 538 got := ld.Linklookup(ctxt, ".got.plt", 0) 539 rel := ld.Linklookup(ctxt, ".rel.plt", 0) 540 if plt.Size == 0 { 541 elfsetupplt() 542 } 543 544 // jmpq *got+size 545 ld.Adduint8(ctxt, plt, 0xff) 546 547 ld.Adduint8(ctxt, plt, 0x25) 548 ld.Addaddrplus(ctxt, plt, got, got.Size) 549 550 // add to got: pointer to current pos in plt 551 ld.Addaddrplus(ctxt, got, plt, plt.Size) 552 553 // pushl $x 554 ld.Adduint8(ctxt, plt, 0x68) 555 556 ld.Adduint32(ctxt, plt, uint32(rel.Size)) 557 558 // jmp .plt 559 ld.Adduint8(ctxt, plt, 0xe9) 560 561 ld.Adduint32(ctxt, plt, uint32(-(plt.Size + 4))) 562 563 // rel 564 ld.Addaddrplus(ctxt, rel, got, got.Size-4) 565 566 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT)) 567 568 s.Plt = int32(plt.Size - 16) 569 } else if ld.HEADTYPE == obj.Hdarwin { 570 // Same laziness as in 6l. 571 572 plt := ld.Linklookup(ctxt, ".plt", 0) 573 574 addgotsym(ctxt, s) 575 576 ld.Adduint32(ctxt, ld.Linklookup(ctxt, ".linkedit.plt", 0), uint32(s.Dynid)) 577 578 // jmpq *got+size(IP) 579 s.Plt = int32(plt.Size) 580 581 ld.Adduint8(ctxt, plt, 0xff) 582 ld.Adduint8(ctxt, plt, 0x25) 583 ld.Addaddrplus(ctxt, plt, ld.Linklookup(ctxt, ".got", 0), int64(s.Got)) 584 } else { 585 ld.Diag("addpltsym: unsupported binary format") 586 } 587 } 588 589 func addgotsym(ctxt *ld.Link, s *ld.LSym) { 590 if s.Got >= 0 { 591 return 592 } 593 594 ld.Adddynsym(ctxt, s) 595 got := ld.Linklookup(ctxt, ".got", 0) 596 s.Got = int32(got.Size) 597 ld.Adduint32(ctxt, got, 0) 598 599 if ld.Iself { 600 rel := ld.Linklookup(ctxt, ".rel", 0) 601 ld.Addaddrplus(ctxt, rel, got, int64(s.Got)) 602 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_GLOB_DAT)) 603 } else if ld.HEADTYPE == obj.Hdarwin { 604 ld.Adduint32(ctxt, ld.Linklookup(ctxt, ".linkedit.got", 0), uint32(s.Dynid)) 605 } else { 606 ld.Diag("addgotsym: unsupported binary format") 607 } 608 } 609 610 func asmb() { 611 if ld.Debug['v'] != 0 { 612 fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime()) 613 } 614 ld.Bso.Flush() 615 616 if ld.Iself { 617 ld.Asmbelfsetup() 618 } 619 620 sect := ld.Segtext.Sect 621 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 622 ld.Codeblk(int64(sect.Vaddr), int64(sect.Length)) 623 for sect = sect.Next; sect != nil; sect = sect.Next { 624 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 625 ld.Datblk(int64(sect.Vaddr), int64(sect.Length)) 626 } 627 628 if ld.Segrodata.Filelen > 0 { 629 if ld.Debug['v'] != 0 { 630 fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime()) 631 } 632 ld.Bso.Flush() 633 634 ld.Cseek(int64(ld.Segrodata.Fileoff)) 635 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 636 } 637 638 if ld.Debug['v'] != 0 { 639 fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime()) 640 } 641 ld.Bso.Flush() 642 643 ld.Cseek(int64(ld.Segdata.Fileoff)) 644 ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 645 646 machlink := uint32(0) 647 if ld.HEADTYPE == obj.Hdarwin { 648 if ld.Debug['v'] != 0 { 649 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 650 } 651 652 dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) 653 ld.Cseek(int64(dwarfoff)) 654 655 ld.Segdwarf.Fileoff = uint64(ld.Cpos()) 656 ld.Dwarfemitdebugsections() 657 ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff 658 659 machlink = uint32(ld.Domacholink()) 660 } 661 662 ld.Symsize = 0 663 ld.Spsize = 0 664 ld.Lcsize = 0 665 symo := uint32(0) 666 if ld.Debug['s'] == 0 { 667 // TODO: rationalize 668 if ld.Debug['v'] != 0 { 669 fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime()) 670 } 671 ld.Bso.Flush() 672 switch ld.HEADTYPE { 673 default: 674 if ld.Iself { 675 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 676 symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND))) 677 } 678 679 case obj.Hplan9: 680 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 681 682 case obj.Hdarwin: 683 symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink)) 684 685 case obj.Hwindows: 686 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 687 symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN)) 688 } 689 690 ld.Cseek(int64(symo)) 691 switch ld.HEADTYPE { 692 default: 693 if ld.Iself { 694 if ld.Debug['v'] != 0 { 695 fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime()) 696 } 697 ld.Asmelfsym() 698 ld.Cflush() 699 ld.Cwrite(ld.Elfstrdat) 700 701 if ld.Debug['v'] != 0 { 702 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 703 } 704 ld.Dwarfemitdebugsections() 705 706 if ld.Linkmode == ld.LinkExternal { 707 ld.Elfemitreloc() 708 } 709 } 710 711 case obj.Hplan9: 712 ld.Asmplan9sym() 713 ld.Cflush() 714 715 sym := ld.Linklookup(ld.Ctxt, "pclntab", 0) 716 if sym != nil { 717 ld.Lcsize = int32(len(sym.P)) 718 for i := 0; int32(i) < ld.Lcsize; i++ { 719 ld.Cput(uint8(sym.P[i])) 720 } 721 722 ld.Cflush() 723 } 724 725 case obj.Hwindows: 726 if ld.Debug['v'] != 0 { 727 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 728 } 729 ld.Dwarfemitdebugsections() 730 731 case obj.Hdarwin: 732 if ld.Linkmode == ld.LinkExternal { 733 ld.Machoemitreloc() 734 } 735 } 736 } 737 738 if ld.Debug['v'] != 0 { 739 fmt.Fprintf(&ld.Bso, "%5.2f headr\n", obj.Cputime()) 740 } 741 ld.Bso.Flush() 742 ld.Cseek(0) 743 switch ld.HEADTYPE { 744 default: 745 case obj.Hplan9: /* plan9 */ 746 magic := int32(4*11*11 + 7) 747 748 ld.Lputb(uint32(magic)) /* magic */ 749 ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */ 750 ld.Lputb(uint32(ld.Segdata.Filelen)) 751 ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 752 ld.Lputb(uint32(ld.Symsize)) /* nsyms */ 753 ld.Lputb(uint32(ld.Entryvalue())) /* va of entry */ 754 ld.Lputb(uint32(ld.Spsize)) /* sp offsets */ 755 ld.Lputb(uint32(ld.Lcsize)) /* line offsets */ 756 757 case obj.Hdarwin: 758 ld.Asmbmacho() 759 760 case obj.Hlinux, 761 obj.Hfreebsd, 762 obj.Hnetbsd, 763 obj.Hopenbsd, 764 obj.Hnacl: 765 ld.Asmbelf(int64(symo)) 766 767 case obj.Hwindows: 768 ld.Asmbpe() 769 } 770 771 ld.Cflush() 772 }