github.com/Filosottile/go@v0.0.0-20170906193555-dbed9972d994/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 (%s)", r.Type, ld.RelocName(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) bool { 349 ld.Thearch.Lput(uint32(sectoff)) 350 351 elfsym := r.Xsym.ElfsymForReloc() 352 switch r.Type { 353 default: 354 return false 355 case objabi.R_ADDR: 356 if r.Siz == 4 { 357 ld.Thearch.Lput(ld.R_386_32 | uint32(elfsym)<<8) 358 } else { 359 return false 360 } 361 case objabi.R_GOTPCREL: 362 if r.Siz == 4 { 363 ld.Thearch.Lput(ld.R_386_GOTPC) 364 if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" { 365 ld.Thearch.Lput(uint32(sectoff)) 366 ld.Thearch.Lput(ld.R_386_GOT32 | uint32(elfsym)<<8) 367 } 368 } else { 369 return false 370 } 371 case objabi.R_CALL: 372 if r.Siz == 4 { 373 if r.Xsym.Type == ld.SDYNIMPORT { 374 ld.Thearch.Lput(ld.R_386_PLT32 | uint32(elfsym)<<8) 375 } else { 376 ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8) 377 } 378 } else { 379 return false 380 } 381 case objabi.R_PCREL: 382 if r.Siz == 4 { 383 ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8) 384 } else { 385 return false 386 } 387 case objabi.R_TLS_LE: 388 if r.Siz == 4 { 389 ld.Thearch.Lput(ld.R_386_TLS_LE | uint32(elfsym)<<8) 390 } else { 391 return false 392 } 393 case objabi.R_TLS_IE: 394 if r.Siz == 4 { 395 ld.Thearch.Lput(ld.R_386_GOTPC) 396 ld.Thearch.Lput(uint32(sectoff)) 397 ld.Thearch.Lput(ld.R_386_TLS_GOTIE | uint32(elfsym)<<8) 398 } else { 399 return false 400 } 401 } 402 403 return true 404 } 405 406 func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { 407 var v uint32 408 409 rs := r.Xsym 410 411 if rs.Type == ld.SHOSTOBJ { 412 if rs.Dynid < 0 { 413 ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, ld.RelocName(r.Type), rs.Name, rs.Type, rs.Type) 414 return false 415 } 416 417 v = uint32(rs.Dynid) 418 v |= 1 << 27 // external relocation 419 } else { 420 v = uint32(rs.Sect.Extnum) 421 if v == 0 { 422 ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, ld.RelocName(r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type) 423 return false 424 } 425 } 426 427 switch r.Type { 428 default: 429 return false 430 case objabi.R_ADDR: 431 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 432 case objabi.R_CALL, 433 objabi.R_PCREL: 434 v |= 1 << 24 // pc-relative bit 435 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 436 } 437 438 switch r.Siz { 439 default: 440 return false 441 case 1: 442 v |= 0 << 25 443 case 2: 444 v |= 1 << 25 445 case 4: 446 v |= 2 << 25 447 case 8: 448 v |= 3 << 25 449 } 450 451 ld.Thearch.Lput(uint32(sectoff)) 452 ld.Thearch.Lput(v) 453 return true 454 } 455 456 func pereloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { 457 var v uint32 458 459 rs := r.Xsym 460 461 if rs.Dynid < 0 { 462 ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, ld.RelocName(r.Type), rs.Name, rs.Type, rs.Type) 463 return false 464 } 465 466 ld.Thearch.Lput(uint32(sectoff)) 467 ld.Thearch.Lput(uint32(rs.Dynid)) 468 469 switch r.Type { 470 default: 471 return false 472 473 case objabi.R_DWARFREF: 474 v = ld.IMAGE_REL_I386_SECREL 475 476 case objabi.R_ADDR: 477 v = ld.IMAGE_REL_I386_DIR32 478 479 case objabi.R_CALL, 480 objabi.R_PCREL: 481 v = ld.IMAGE_REL_I386_REL32 482 } 483 484 ld.Thearch.Wput(uint16(v)) 485 486 return true 487 } 488 489 func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { 490 if ld.Linkmode == ld.LinkExternal { 491 return false 492 } 493 switch r.Type { 494 case objabi.R_CONST: 495 *val = r.Add 496 return true 497 case objabi.R_GOTOFF: 498 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)) 499 return true 500 } 501 502 return false 503 } 504 505 func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { 506 log.Fatalf("unexpected relocation variant") 507 return t 508 } 509 510 func elfsetupplt(ctxt *ld.Link) { 511 plt := ctxt.Syms.Lookup(".plt", 0) 512 got := ctxt.Syms.Lookup(".got.plt", 0) 513 if plt.Size == 0 { 514 // pushl got+4 515 ld.Adduint8(ctxt, plt, 0xff) 516 517 ld.Adduint8(ctxt, plt, 0x35) 518 ld.Addaddrplus(ctxt, plt, got, 4) 519 520 // jmp *got+8 521 ld.Adduint8(ctxt, plt, 0xff) 522 523 ld.Adduint8(ctxt, plt, 0x25) 524 ld.Addaddrplus(ctxt, plt, got, 8) 525 526 // zero pad 527 ld.Adduint32(ctxt, plt, 0) 528 529 // assume got->size == 0 too 530 ld.Addaddrplus(ctxt, got, ctxt.Syms.Lookup(".dynamic", 0), 0) 531 532 ld.Adduint32(ctxt, got, 0) 533 ld.Adduint32(ctxt, got, 0) 534 } 535 } 536 537 func addpltsym(ctxt *ld.Link, s *ld.Symbol) { 538 if s.Plt >= 0 { 539 return 540 } 541 542 ld.Adddynsym(ctxt, s) 543 544 if ld.Iself { 545 plt := ctxt.Syms.Lookup(".plt", 0) 546 got := ctxt.Syms.Lookup(".got.plt", 0) 547 rel := ctxt.Syms.Lookup(".rel.plt", 0) 548 if plt.Size == 0 { 549 elfsetupplt(ctxt) 550 } 551 552 // jmpq *got+size 553 ld.Adduint8(ctxt, plt, 0xff) 554 555 ld.Adduint8(ctxt, plt, 0x25) 556 ld.Addaddrplus(ctxt, plt, got, got.Size) 557 558 // add to got: pointer to current pos in plt 559 ld.Addaddrplus(ctxt, got, plt, plt.Size) 560 561 // pushl $x 562 ld.Adduint8(ctxt, plt, 0x68) 563 564 ld.Adduint32(ctxt, plt, uint32(rel.Size)) 565 566 // jmp .plt 567 ld.Adduint8(ctxt, plt, 0xe9) 568 569 ld.Adduint32(ctxt, plt, uint32(-(plt.Size + 4))) 570 571 // rel 572 ld.Addaddrplus(ctxt, rel, got, got.Size-4) 573 574 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT)) 575 576 s.Plt = int32(plt.Size - 16) 577 } else if ld.Headtype == objabi.Hdarwin { 578 // Same laziness as in 6l. 579 580 plt := ctxt.Syms.Lookup(".plt", 0) 581 582 addgotsym(ctxt, s) 583 584 ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.plt", 0), uint32(s.Dynid)) 585 586 // jmpq *got+size(IP) 587 s.Plt = int32(plt.Size) 588 589 ld.Adduint8(ctxt, plt, 0xff) 590 ld.Adduint8(ctxt, plt, 0x25) 591 ld.Addaddrplus(ctxt, plt, ctxt.Syms.Lookup(".got", 0), int64(s.Got)) 592 } else { 593 ld.Errorf(s, "addpltsym: unsupported binary format") 594 } 595 } 596 597 func addgotsym(ctxt *ld.Link, s *ld.Symbol) { 598 if s.Got >= 0 { 599 return 600 } 601 602 ld.Adddynsym(ctxt, s) 603 got := ctxt.Syms.Lookup(".got", 0) 604 s.Got = int32(got.Size) 605 ld.Adduint32(ctxt, got, 0) 606 607 if ld.Iself { 608 rel := ctxt.Syms.Lookup(".rel", 0) 609 ld.Addaddrplus(ctxt, rel, got, int64(s.Got)) 610 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_GLOB_DAT)) 611 } else if ld.Headtype == objabi.Hdarwin { 612 ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.got", 0), uint32(s.Dynid)) 613 } else { 614 ld.Errorf(s, "addgotsym: unsupported binary format") 615 } 616 } 617 618 func asmb(ctxt *ld.Link) { 619 if ctxt.Debugvlog != 0 { 620 ctxt.Logf("%5.2f asmb\n", ld.Cputime()) 621 } 622 623 if ld.Iself { 624 ld.Asmbelfsetup() 625 } 626 627 sect := ld.Segtext.Sections[0] 628 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 629 // 0xCC is INT $3 - breakpoint instruction 630 ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC}) 631 for _, sect = range ld.Segtext.Sections[1:] { 632 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 633 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 634 } 635 636 if ld.Segrodata.Filelen > 0 { 637 if ctxt.Debugvlog != 0 { 638 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime()) 639 } 640 641 ld.Cseek(int64(ld.Segrodata.Fileoff)) 642 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 643 } 644 if ld.Segrelrodata.Filelen > 0 { 645 if ctxt.Debugvlog != 0 { 646 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime()) 647 } 648 ld.Cseek(int64(ld.Segrelrodata.Fileoff)) 649 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen)) 650 } 651 652 if ctxt.Debugvlog != 0 { 653 ctxt.Logf("%5.2f datblk\n", ld.Cputime()) 654 } 655 656 ld.Cseek(int64(ld.Segdata.Fileoff)) 657 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 658 659 ld.Cseek(int64(ld.Segdwarf.Fileoff)) 660 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 661 662 machlink := uint32(0) 663 if ld.Headtype == objabi.Hdarwin { 664 machlink = uint32(ld.Domacholink(ctxt)) 665 } 666 667 ld.Symsize = 0 668 ld.Spsize = 0 669 ld.Lcsize = 0 670 symo := uint32(0) 671 if !*ld.FlagS { 672 // TODO: rationalize 673 if ctxt.Debugvlog != 0 { 674 ctxt.Logf("%5.2f sym\n", ld.Cputime()) 675 } 676 switch ld.Headtype { 677 default: 678 if ld.Iself { 679 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 680 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 681 } 682 683 case objabi.Hplan9: 684 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 685 686 case objabi.Hdarwin: 687 symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink)) 688 689 case objabi.Hwindows: 690 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 691 symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN)) 692 } 693 694 ld.Cseek(int64(symo)) 695 switch ld.Headtype { 696 default: 697 if ld.Iself { 698 if ctxt.Debugvlog != 0 { 699 ctxt.Logf("%5.2f elfsym\n", ld.Cputime()) 700 } 701 ld.Asmelfsym(ctxt) 702 ld.Cflush() 703 ld.Cwrite(ld.Elfstrdat) 704 705 if ld.Linkmode == ld.LinkExternal { 706 ld.Elfemitreloc(ctxt) 707 } 708 } 709 710 case objabi.Hplan9: 711 ld.Asmplan9sym(ctxt) 712 ld.Cflush() 713 714 sym := ctxt.Syms.Lookup("pclntab", 0) 715 if sym != nil { 716 ld.Lcsize = int32(len(sym.P)) 717 for i := 0; int32(i) < ld.Lcsize; i++ { 718 ld.Cput(sym.P[i]) 719 } 720 721 ld.Cflush() 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 ld.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 ld.Cseek(0) 740 switch ld.Headtype { 741 default: 742 case objabi.Hplan9: /* plan9 */ 743 magic := int32(4*11*11 + 7) 744 745 ld.Lputb(uint32(magic)) /* magic */ 746 ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */ 747 ld.Lputb(uint32(ld.Segdata.Filelen)) 748 ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 749 ld.Lputb(uint32(ld.Symsize)) /* nsyms */ 750 ld.Lputb(uint32(ld.Entryvalue(ctxt))) /* va of entry */ 751 ld.Lputb(uint32(ld.Spsize)) /* sp offsets */ 752 ld.Lputb(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 ld.Cflush() 769 }