github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/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 "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 addpltsym(ctxt, targ) 301 r.Sym = ctxt.Syms.Lookup(".plt", 0) 302 r.Add = int64(targ.Plt) 303 return true 304 305 case objabi.R_ADDR: 306 if s.Type != sym.SDATA { 307 break 308 } 309 if ctxt.IsELF { 310 ld.Adddynsym(ctxt, targ) 311 rel := ctxt.Syms.Lookup(".rel", 0) 312 rel.AddAddrPlus(ctxt.Arch, s, int64(r.Off)) 313 rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_386_32))) 314 r.Type = objabi.R_CONST // write r->add during relocsym 315 r.Sym = nil 316 return true 317 } 318 319 if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 { 320 // Mach-O relocations are a royal pain to lay out. 321 // They use a compact stateful bytecode representation 322 // that is too much bother to deal with. 323 // Instead, interpret the C declaration 324 // void *_Cvar_stderr = &stderr; 325 // as making _Cvar_stderr the name of a GOT entry 326 // for stderr. This is separate from the usual GOT entry, 327 // just in case the C code assigns to the variable, 328 // and of course it only works for single pointers, 329 // but we only need to support cgo and that's all it needs. 330 ld.Adddynsym(ctxt, targ) 331 332 got := ctxt.Syms.Lookup(".got", 0) 333 s.Type = got.Type 334 s.Attr |= sym.AttrSubSymbol 335 s.Outer = got 336 s.Sub = got.Sub 337 got.Sub = s 338 s.Value = got.Size 339 got.AddUint32(ctxt.Arch, 0) 340 ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid)) 341 r.Type = 256 // ignore during relocsym 342 return true 343 } 344 } 345 346 return false 347 } 348 349 func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { 350 ctxt.Out.Write32(uint32(sectoff)) 351 352 elfsym := r.Xsym.ElfsymForReloc() 353 switch r.Type { 354 default: 355 return false 356 case objabi.R_ADDR: 357 if r.Siz == 4 { 358 ctxt.Out.Write32(uint32(elf.R_386_32) | uint32(elfsym)<<8) 359 } else { 360 return false 361 } 362 case objabi.R_GOTPCREL: 363 if r.Siz == 4 { 364 ctxt.Out.Write32(uint32(elf.R_386_GOTPC)) 365 if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" { 366 ctxt.Out.Write32(uint32(sectoff)) 367 ctxt.Out.Write32(uint32(elf.R_386_GOT32) | uint32(elfsym)<<8) 368 } 369 } else { 370 return false 371 } 372 case objabi.R_CALL: 373 if r.Siz == 4 { 374 if r.Xsym.Type == sym.SDYNIMPORT { 375 ctxt.Out.Write32(uint32(elf.R_386_PLT32) | uint32(elfsym)<<8) 376 } else { 377 ctxt.Out.Write32(uint32(elf.R_386_PC32) | uint32(elfsym)<<8) 378 } 379 } else { 380 return false 381 } 382 case objabi.R_PCREL: 383 if r.Siz == 4 { 384 ctxt.Out.Write32(uint32(elf.R_386_PC32) | uint32(elfsym)<<8) 385 } else { 386 return false 387 } 388 case objabi.R_TLS_LE: 389 if r.Siz == 4 { 390 ctxt.Out.Write32(uint32(elf.R_386_TLS_LE) | uint32(elfsym)<<8) 391 } else { 392 return false 393 } 394 case objabi.R_TLS_IE: 395 if r.Siz == 4 { 396 ctxt.Out.Write32(uint32(elf.R_386_GOTPC)) 397 ctxt.Out.Write32(uint32(sectoff)) 398 ctxt.Out.Write32(uint32(elf.R_386_TLS_GOTIE) | uint32(elfsym)<<8) 399 } else { 400 return false 401 } 402 } 403 404 return true 405 } 406 407 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool { 408 var v uint32 409 410 rs := r.Xsym 411 412 if rs.Type == sym.SHOSTOBJ { 413 if rs.Dynid < 0 { 414 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) 415 return false 416 } 417 418 v = uint32(rs.Dynid) 419 v |= 1 << 27 // external relocation 420 } else { 421 v = uint32(rs.Sect.Extnum) 422 if v == 0 { 423 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) 424 return false 425 } 426 } 427 428 switch r.Type { 429 default: 430 return false 431 case objabi.R_ADDR: 432 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 433 case objabi.R_CALL, 434 objabi.R_PCREL: 435 v |= 1 << 24 // pc-relative bit 436 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 437 } 438 439 switch r.Siz { 440 default: 441 return false 442 case 1: 443 v |= 0 << 25 444 case 2: 445 v |= 1 << 25 446 case 4: 447 v |= 2 << 25 448 case 8: 449 v |= 3 << 25 450 } 451 452 out.Write32(uint32(sectoff)) 453 out.Write32(v) 454 return true 455 } 456 457 func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool { 458 var v uint32 459 460 rs := r.Xsym 461 462 if rs.Dynid < 0 { 463 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) 464 return false 465 } 466 467 out.Write32(uint32(sectoff)) 468 out.Write32(uint32(rs.Dynid)) 469 470 switch r.Type { 471 default: 472 return false 473 474 case objabi.R_DWARFSECREF: 475 v = ld.IMAGE_REL_I386_SECREL 476 477 case objabi.R_ADDR: 478 v = ld.IMAGE_REL_I386_DIR32 479 480 case objabi.R_CALL, 481 objabi.R_PCREL: 482 v = ld.IMAGE_REL_I386_REL32 483 } 484 485 out.Write16(uint16(v)) 486 487 return true 488 } 489 490 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool { 491 if ctxt.LinkMode == ld.LinkExternal { 492 return false 493 } 494 switch r.Type { 495 case objabi.R_CONST: 496 *val = r.Add 497 return true 498 case objabi.R_GOTOFF: 499 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)) 500 return true 501 } 502 503 return false 504 } 505 506 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 { 507 log.Fatalf("unexpected relocation variant") 508 return t 509 } 510 511 func elfsetupplt(ctxt *ld.Link) { 512 plt := ctxt.Syms.Lookup(".plt", 0) 513 got := ctxt.Syms.Lookup(".got.plt", 0) 514 if plt.Size == 0 { 515 // pushl got+4 516 plt.AddUint8(0xff) 517 518 plt.AddUint8(0x35) 519 plt.AddAddrPlus(ctxt.Arch, got, 4) 520 521 // jmp *got+8 522 plt.AddUint8(0xff) 523 524 plt.AddUint8(0x25) 525 plt.AddAddrPlus(ctxt.Arch, got, 8) 526 527 // zero pad 528 plt.AddUint32(ctxt.Arch, 0) 529 530 // assume got->size == 0 too 531 got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0) 532 533 got.AddUint32(ctxt.Arch, 0) 534 got.AddUint32(ctxt.Arch, 0) 535 } 536 } 537 538 func addpltsym(ctxt *ld.Link, s *sym.Symbol) { 539 if s.Plt >= 0 { 540 return 541 } 542 543 ld.Adddynsym(ctxt, s) 544 545 if ctxt.IsELF { 546 plt := ctxt.Syms.Lookup(".plt", 0) 547 got := ctxt.Syms.Lookup(".got.plt", 0) 548 rel := ctxt.Syms.Lookup(".rel.plt", 0) 549 if plt.Size == 0 { 550 elfsetupplt(ctxt) 551 } 552 553 // jmpq *got+size 554 plt.AddUint8(0xff) 555 556 plt.AddUint8(0x25) 557 plt.AddAddrPlus(ctxt.Arch, got, got.Size) 558 559 // add to got: pointer to current pos in plt 560 got.AddAddrPlus(ctxt.Arch, plt, plt.Size) 561 562 // pushl $x 563 plt.AddUint8(0x68) 564 565 plt.AddUint32(ctxt.Arch, uint32(rel.Size)) 566 567 // jmp .plt 568 plt.AddUint8(0xe9) 569 570 plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4))) 571 572 // rel 573 rel.AddAddrPlus(ctxt.Arch, got, got.Size-4) 574 575 rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_JMP_SLOT))) 576 577 s.Plt = int32(plt.Size - 16) 578 } else if ctxt.HeadType == objabi.Hdarwin { 579 // Same laziness as in 6l. 580 581 plt := ctxt.Syms.Lookup(".plt", 0) 582 583 addgotsym(ctxt, s) 584 585 ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid)) 586 587 // jmpq *got+size(IP) 588 s.Plt = int32(plt.Size) 589 590 plt.AddUint8(0xff) 591 plt.AddUint8(0x25) 592 plt.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got)) 593 } else { 594 ld.Errorf(s, "addpltsym: unsupported binary format") 595 } 596 } 597 598 func addgotsym(ctxt *ld.Link, s *sym.Symbol) { 599 if s.Got >= 0 { 600 return 601 } 602 603 ld.Adddynsym(ctxt, s) 604 got := ctxt.Syms.Lookup(".got", 0) 605 s.Got = int32(got.Size) 606 got.AddUint32(ctxt.Arch, 0) 607 608 if ctxt.IsELF { 609 rel := ctxt.Syms.Lookup(".rel", 0) 610 rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got)) 611 rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_GLOB_DAT))) 612 } else if ctxt.HeadType == objabi.Hdarwin { 613 ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid)) 614 } else { 615 ld.Errorf(s, "addgotsym: unsupported binary format") 616 } 617 } 618 619 func asmb(ctxt *ld.Link) { 620 if ctxt.Debugvlog != 0 { 621 ctxt.Logf("%5.2f asmb\n", ld.Cputime()) 622 } 623 624 if ctxt.IsELF { 625 ld.Asmbelfsetup() 626 } 627 628 sect := ld.Segtext.Sections[0] 629 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 630 // 0xCC is INT $3 - breakpoint instruction 631 ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC}) 632 for _, sect = range ld.Segtext.Sections[1:] { 633 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 634 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 635 } 636 637 if ld.Segrodata.Filelen > 0 { 638 if ctxt.Debugvlog != 0 { 639 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime()) 640 } 641 642 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff)) 643 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 644 } 645 if ld.Segrelrodata.Filelen > 0 { 646 if ctxt.Debugvlog != 0 { 647 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime()) 648 } 649 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff)) 650 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen)) 651 } 652 653 if ctxt.Debugvlog != 0 { 654 ctxt.Logf("%5.2f datblk\n", ld.Cputime()) 655 } 656 657 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff)) 658 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 659 660 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff)) 661 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 662 663 machlink := uint32(0) 664 if ctxt.HeadType == objabi.Hdarwin { 665 machlink = uint32(ld.Domacholink(ctxt)) 666 } 667 668 ld.Symsize = 0 669 ld.Spsize = 0 670 ld.Lcsize = 0 671 symo := uint32(0) 672 if !*ld.FlagS { 673 // TODO: rationalize 674 if ctxt.Debugvlog != 0 { 675 ctxt.Logf("%5.2f sym\n", ld.Cputime()) 676 } 677 switch ctxt.HeadType { 678 default: 679 if ctxt.IsELF { 680 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 681 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 682 } 683 684 case objabi.Hplan9: 685 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 686 687 case objabi.Hdarwin: 688 symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink)) 689 690 case objabi.Hwindows: 691 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 692 symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN)) 693 } 694 695 ctxt.Out.SeekSet(int64(symo)) 696 switch ctxt.HeadType { 697 default: 698 if ctxt.IsELF { 699 if ctxt.Debugvlog != 0 { 700 ctxt.Logf("%5.2f elfsym\n", ld.Cputime()) 701 } 702 ld.Asmelfsym(ctxt) 703 ctxt.Out.Flush() 704 ctxt.Out.Write(ld.Elfstrdat) 705 706 if ctxt.LinkMode == ld.LinkExternal { 707 ld.Elfemitreloc(ctxt) 708 } 709 } 710 711 case objabi.Hplan9: 712 ld.Asmplan9sym(ctxt) 713 ctxt.Out.Flush() 714 715 sym := ctxt.Syms.Lookup("pclntab", 0) 716 if sym != nil { 717 ld.Lcsize = int32(len(sym.P)) 718 ctxt.Out.Write(sym.P) 719 ctxt.Out.Flush() 720 } 721 722 case objabi.Hwindows: 723 if ctxt.Debugvlog != 0 { 724 ctxt.Logf("%5.2f dwarf\n", ld.Cputime()) 725 } 726 727 case objabi.Hdarwin: 728 if ctxt.LinkMode == ld.LinkExternal { 729 ld.Machoemitreloc(ctxt) 730 } 731 } 732 } 733 734 if ctxt.Debugvlog != 0 { 735 ctxt.Logf("%5.2f headr\n", ld.Cputime()) 736 } 737 ctxt.Out.SeekSet(0) 738 switch ctxt.HeadType { 739 default: 740 case objabi.Hplan9: /* plan9 */ 741 magic := int32(4*11*11 + 7) 742 743 ctxt.Out.Write32b(uint32(magic)) /* magic */ 744 ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */ 745 ctxt.Out.Write32b(uint32(ld.Segdata.Filelen)) 746 ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 747 ctxt.Out.Write32b(uint32(ld.Symsize)) /* nsyms */ 748 ctxt.Out.Write32b(uint32(ld.Entryvalue(ctxt))) /* va of entry */ 749 ctxt.Out.Write32b(uint32(ld.Spsize)) /* sp offsets */ 750 ctxt.Out.Write32b(uint32(ld.Lcsize)) /* line offsets */ 751 752 case objabi.Hdarwin: 753 ld.Asmbmacho(ctxt) 754 755 case objabi.Hlinux, 756 objabi.Hfreebsd, 757 objabi.Hnetbsd, 758 objabi.Hopenbsd, 759 objabi.Hnacl: 760 ld.Asmbelf(ctxt, int64(symo)) 761 762 case objabi.Hwindows: 763 ld.Asmbpe(ctxt) 764 } 765 766 ctxt.Out.Flush() 767 }