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