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