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