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 (a] 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 (a] 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/obj" 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 = obj.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 = obj.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 == obj.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 = obj.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 = obj.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 = obj.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 == obj.SDYNIMPORT { 180 ld.Errorf(s, "unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name) 181 } 182 if targ.Type == 0 || targ.Type == obj.SXREF { 183 ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name) 184 } 185 r.Type = obj.R_PCREL 186 r.Add += 4 187 return true 188 189 case 256 + ld.R_386_PLT32: 190 r.Type = obj.R_PCREL 191 r.Add += 4 192 if targ.Type == obj.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 != obj.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 = obj.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 = obj.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 = obj.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 = obj.R_GOTOFF 233 return true 234 235 case 256 + ld.R_386_GOTPC: 236 r.Type = obj.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 == obj.SDYNIMPORT { 243 ld.Errorf(s, "unexpected R_386_32 relocation for dynamic symbol %s", targ.Name) 244 } 245 r.Type = obj.R_ADDR 246 return true 247 248 case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0: 249 r.Type = obj.R_ADDR 250 if targ.Type == obj.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 == obj.SDYNIMPORT { 257 addpltsym(ctxt, targ) 258 r.Sym = ctxt.Syms.Lookup(".plt", 0) 259 r.Add = int64(targ.Plt) 260 r.Type = obj.R_PCREL 261 return true 262 } 263 264 r.Type = obj.R_PCREL 265 return true 266 267 case 512 + ld.MACHO_FAKE_GOTPCREL: 268 if targ.Type != obj.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 = obj.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 = obj.R_PCREL 285 return true 286 } 287 288 // Handle references to ELF symbols from our own object files. 289 if targ.Type != obj.SDYNIMPORT { 290 return true 291 } 292 switch r.Type { 293 case obj.R_CALL, 294 obj.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 obj.R_ADDR: 301 if s.Type != obj.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 = obj.R_CONST // write r->add during relocsym 310 r.Sym = nil 311 return true 312 } 313 314 if ld.Headtype == obj.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 | obj.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 == obj.Hwindows || ld.Headtype == obj.Hwindowsgui) && 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 obj.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 obj.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 obj.R_CALL: 375 if r.Siz == 4 { 376 if r.Xsym.Type == obj.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 obj.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 obj.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 obj.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 == obj.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 obj.R_ADDR: 438 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 439 440 case obj.R_CALL, 441 obj.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 obj.R_ADDR: 486 v = ld.IMAGE_REL_I386_DIR32 487 488 case obj.R_CALL, 489 obj.R_PCREL: 490 v = ld.IMAGE_REL_I386_REL32 491 } 492 493 ld.Thearch.Wput(uint16(v)) 494 495 return true 496 } 497 498 func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int { 499 if ld.Linkmode == ld.LinkExternal { 500 return -1 501 } 502 switch r.Type { 503 case obj.R_CONST: 504 *val = r.Add 505 return 0 506 507 case obj.R_GOTOFF: 508 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)) 509 return 0 510 } 511 512 return -1 513 } 514 515 func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { 516 log.Fatalf("unexpected relocation variant") 517 return t 518 } 519 520 func elfsetupplt(ctxt *ld.Link) { 521 plt := ctxt.Syms.Lookup(".plt", 0) 522 got := ctxt.Syms.Lookup(".got.plt", 0) 523 if plt.Size == 0 { 524 // pushl got+4 525 ld.Adduint8(ctxt, plt, 0xff) 526 527 ld.Adduint8(ctxt, plt, 0x35) 528 ld.Addaddrplus(ctxt, plt, got, 4) 529 530 // jmp *got+8 531 ld.Adduint8(ctxt, plt, 0xff) 532 533 ld.Adduint8(ctxt, plt, 0x25) 534 ld.Addaddrplus(ctxt, plt, got, 8) 535 536 // zero pad 537 ld.Adduint32(ctxt, plt, 0) 538 539 // assume got->size == 0 too 540 ld.Addaddrplus(ctxt, got, ctxt.Syms.Lookup(".dynamic", 0), 0) 541 542 ld.Adduint32(ctxt, got, 0) 543 ld.Adduint32(ctxt, got, 0) 544 } 545 } 546 547 func addpltsym(ctxt *ld.Link, s *ld.Symbol) { 548 if s.Plt >= 0 { 549 return 550 } 551 552 ld.Adddynsym(ctxt, s) 553 554 if ld.Iself { 555 plt := ctxt.Syms.Lookup(".plt", 0) 556 got := ctxt.Syms.Lookup(".got.plt", 0) 557 rel := ctxt.Syms.Lookup(".rel.plt", 0) 558 if plt.Size == 0 { 559 elfsetupplt(ctxt) 560 } 561 562 // jmpq *got+size 563 ld.Adduint8(ctxt, plt, 0xff) 564 565 ld.Adduint8(ctxt, plt, 0x25) 566 ld.Addaddrplus(ctxt, plt, got, got.Size) 567 568 // add to got: pointer to current pos in plt 569 ld.Addaddrplus(ctxt, got, plt, plt.Size) 570 571 // pushl $x 572 ld.Adduint8(ctxt, plt, 0x68) 573 574 ld.Adduint32(ctxt, plt, uint32(rel.Size)) 575 576 // jmp .plt 577 ld.Adduint8(ctxt, plt, 0xe9) 578 579 ld.Adduint32(ctxt, plt, uint32(-(plt.Size + 4))) 580 581 // rel 582 ld.Addaddrplus(ctxt, rel, got, got.Size-4) 583 584 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT)) 585 586 s.Plt = int32(plt.Size - 16) 587 } else if ld.Headtype == obj.Hdarwin { 588 // Same laziness as in 6l. 589 590 plt := ctxt.Syms.Lookup(".plt", 0) 591 592 addgotsym(ctxt, s) 593 594 ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.plt", 0), uint32(s.Dynid)) 595 596 // jmpq *got+size(IP) 597 s.Plt = int32(plt.Size) 598 599 ld.Adduint8(ctxt, plt, 0xff) 600 ld.Adduint8(ctxt, plt, 0x25) 601 ld.Addaddrplus(ctxt, plt, ctxt.Syms.Lookup(".got", 0), int64(s.Got)) 602 } else { 603 ld.Errorf(s, "addpltsym: unsupported binary format") 604 } 605 } 606 607 func addgotsym(ctxt *ld.Link, s *ld.Symbol) { 608 if s.Got >= 0 { 609 return 610 } 611 612 ld.Adddynsym(ctxt, s) 613 got := ctxt.Syms.Lookup(".got", 0) 614 s.Got = int32(got.Size) 615 ld.Adduint32(ctxt, got, 0) 616 617 if ld.Iself { 618 rel := ctxt.Syms.Lookup(".rel", 0) 619 ld.Addaddrplus(ctxt, rel, got, int64(s.Got)) 620 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_GLOB_DAT)) 621 } else if ld.Headtype == obj.Hdarwin { 622 ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.got", 0), uint32(s.Dynid)) 623 } else { 624 ld.Errorf(s, "addgotsym: unsupported binary format") 625 } 626 } 627 628 func asmb(ctxt *ld.Link) { 629 if ctxt.Debugvlog != 0 { 630 ctxt.Logf("%5.2f asmb\n", obj.Cputime()) 631 } 632 633 if ld.Iself { 634 ld.Asmbelfsetup() 635 } 636 637 sect := ld.Segtext.Sect 638 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 639 // 0xCC is INT $3 - breakpoint instruction 640 ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC}) 641 for sect = sect.Next; sect != nil; sect = sect.Next { 642 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 643 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 644 } 645 646 if ld.Segrodata.Filelen > 0 { 647 if ctxt.Debugvlog != 0 { 648 ctxt.Logf("%5.2f rodatblk\n", obj.Cputime()) 649 } 650 651 ld.Cseek(int64(ld.Segrodata.Fileoff)) 652 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 653 } 654 if ld.Segrelrodata.Filelen > 0 { 655 if ctxt.Debugvlog != 0 { 656 ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime()) 657 } 658 ld.Cseek(int64(ld.Segrelrodata.Fileoff)) 659 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen)) 660 } 661 662 if ctxt.Debugvlog != 0 { 663 ctxt.Logf("%5.2f datblk\n", obj.Cputime()) 664 } 665 666 ld.Cseek(int64(ld.Segdata.Fileoff)) 667 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 668 669 ld.Cseek(int64(ld.Segdwarf.Fileoff)) 670 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 671 672 machlink := uint32(0) 673 if ld.Headtype == obj.Hdarwin { 674 machlink = uint32(ld.Domacholink(ctxt)) 675 } 676 677 ld.Symsize = 0 678 ld.Spsize = 0 679 ld.Lcsize = 0 680 symo := uint32(0) 681 if !*ld.FlagS { 682 // TODO: rationalize 683 if ctxt.Debugvlog != 0 { 684 ctxt.Logf("%5.2f sym\n", obj.Cputime()) 685 } 686 switch ld.Headtype { 687 default: 688 if ld.Iself { 689 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 690 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 691 } 692 693 case obj.Hplan9: 694 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 695 696 case obj.Hdarwin: 697 symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink)) 698 699 case obj.Hwindows, obj.Hwindowsgui: 700 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 701 symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN)) 702 } 703 704 ld.Cseek(int64(symo)) 705 switch ld.Headtype { 706 default: 707 if ld.Iself { 708 if ctxt.Debugvlog != 0 { 709 ctxt.Logf("%5.2f elfsym\n", obj.Cputime()) 710 } 711 ld.Asmelfsym(ctxt) 712 ld.Cflush() 713 ld.Cwrite(ld.Elfstrdat) 714 715 if ld.Linkmode == ld.LinkExternal { 716 ld.Elfemitreloc(ctxt) 717 } 718 } 719 720 case obj.Hplan9: 721 ld.Asmplan9sym(ctxt) 722 ld.Cflush() 723 724 sym := ctxt.Syms.Lookup("pclntab", 0) 725 if sym != nil { 726 ld.Lcsize = int32(len(sym.P)) 727 for i := 0; int32(i) < ld.Lcsize; i++ { 728 ld.Cput(sym.P[i]) 729 } 730 731 ld.Cflush() 732 } 733 734 case obj.Hwindows, obj.Hwindowsgui: 735 if ctxt.Debugvlog != 0 { 736 ctxt.Logf("%5.2f dwarf\n", obj.Cputime()) 737 } 738 739 case obj.Hdarwin: 740 if ld.Linkmode == ld.LinkExternal { 741 ld.Machoemitreloc(ctxt) 742 } 743 } 744 } 745 746 if ctxt.Debugvlog != 0 { 747 ctxt.Logf("%5.2f headr\n", obj.Cputime()) 748 } 749 ld.Cseek(0) 750 switch ld.Headtype { 751 default: 752 case obj.Hplan9: /* plan9 */ 753 magic := int32(4*11*11 + 7) 754 755 ld.Lputb(uint32(magic)) /* magic */ 756 ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */ 757 ld.Lputb(uint32(ld.Segdata.Filelen)) 758 ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 759 ld.Lputb(uint32(ld.Symsize)) /* nsyms */ 760 ld.Lputb(uint32(ld.Entryvalue(ctxt))) /* va of entry */ 761 ld.Lputb(uint32(ld.Spsize)) /* sp offsets */ 762 ld.Lputb(uint32(ld.Lcsize)) /* line offsets */ 763 764 case obj.Hdarwin: 765 ld.Asmbmacho(ctxt) 766 767 case obj.Hlinux, 768 obj.Hfreebsd, 769 obj.Hnetbsd, 770 obj.Hopenbsd, 771 obj.Hnacl: 772 ld.Asmbelf(ctxt, int64(symo)) 773 774 case obj.Hwindows, obj.Hwindowsgui: 775 ld.Asmbpe(ctxt) 776 } 777 778 ld.Cflush() 779 } 780