rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/cmd/8l/asm.go (about) 1 // Inferno utils/8l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/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 main 32 33 import ( 34 "cmd/internal/ld" 35 "cmd/internal/obj" 36 "fmt" 37 "log" 38 ) 39 40 func needlib(name string) int { 41 if name[0] == '\x00' { 42 return 0 43 } 44 45 /* reuse hash code in symbol table */ 46 p := fmt.Sprintf(".dynlib.%s", name) 47 48 s := ld.Linklookup(ld.Ctxt, p, 0) 49 50 if s.Type == 0 { 51 s.Type = 100 // avoid SDATA, etc. 52 return 1 53 } 54 55 return 0 56 } 57 58 func gentext() { 59 } 60 61 func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { 62 log.Fatalf("adddynrela not implemented") 63 } 64 65 func adddynrel(s *ld.LSym, r *ld.Reloc) { 66 targ := r.Sym 67 ld.Ctxt.Cursym = s 68 69 switch r.Type { 70 default: 71 if r.Type >= 256 { 72 ld.Diag("unexpected relocation type %d", r.Type) 73 return 74 } 75 76 // Handle relocations found in ELF object files. 77 case 256 + ld.R_386_PC32: 78 if targ.Type == ld.SDYNIMPORT { 79 ld.Diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name) 80 } 81 if targ.Type == 0 || targ.Type == ld.SXREF { 82 ld.Diag("unknown symbol %s in pcrel", targ.Name) 83 } 84 r.Type = ld.R_PCREL 85 r.Add += 4 86 return 87 88 case 256 + ld.R_386_PLT32: 89 r.Type = ld.R_PCREL 90 r.Add += 4 91 if targ.Type == ld.SDYNIMPORT { 92 addpltsym(ld.Ctxt, targ) 93 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 94 r.Add += int64(targ.Plt) 95 } 96 97 return 98 99 case 256 + ld.R_386_GOT32: 100 if targ.Type != ld.SDYNIMPORT { 101 // have symbol 102 if r.Off >= 2 && s.P[r.Off-2] == 0x8b { 103 // turn MOVL of GOT entry into LEAL of symbol address, relative to GOT. 104 s.P[r.Off-2] = 0x8d 105 106 r.Type = ld.R_GOTOFF 107 return 108 } 109 110 if r.Off >= 2 && s.P[r.Off-2] == 0xff && s.P[r.Off-1] == 0xb3 { 111 // turn PUSHL of GOT entry into PUSHL of symbol itself. 112 // use unnecessary SS prefix to keep instruction same length. 113 s.P[r.Off-2] = 0x36 114 115 s.P[r.Off-1] = 0x68 116 r.Type = ld.R_ADDR 117 return 118 } 119 120 ld.Diag("unexpected GOT reloc for non-dynamic symbol %s", targ.Name) 121 return 122 } 123 124 addgotsym(ld.Ctxt, targ) 125 r.Type = ld.R_CONST // write r->add during relocsym 126 r.Sym = nil 127 r.Add += int64(targ.Got) 128 return 129 130 case 256 + ld.R_386_GOTOFF: 131 r.Type = ld.R_GOTOFF 132 return 133 134 case 256 + ld.R_386_GOTPC: 135 r.Type = ld.R_PCREL 136 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 137 r.Add += 4 138 return 139 140 case 256 + ld.R_386_32: 141 if targ.Type == ld.SDYNIMPORT { 142 ld.Diag("unexpected R_386_32 relocation for dynamic symbol %s", targ.Name) 143 } 144 r.Type = ld.R_ADDR 145 return 146 147 case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0: 148 r.Type = ld.R_ADDR 149 if targ.Type == ld.SDYNIMPORT { 150 ld.Diag("unexpected reloc for dynamic symbol %s", targ.Name) 151 } 152 return 153 154 case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1: 155 if targ.Type == ld.SDYNIMPORT { 156 addpltsym(ld.Ctxt, targ) 157 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 158 r.Add = int64(targ.Plt) 159 r.Type = ld.R_PCREL 160 return 161 } 162 163 r.Type = ld.R_PCREL 164 return 165 166 case 512 + ld.MACHO_FAKE_GOTPCREL: 167 if targ.Type != ld.SDYNIMPORT { 168 // have symbol 169 // turn MOVL of GOT entry into LEAL of symbol itself 170 if r.Off < 2 || s.P[r.Off-2] != 0x8b { 171 ld.Diag("unexpected GOT reloc for non-dynamic symbol %s", targ.Name) 172 return 173 } 174 175 s.P[r.Off-2] = 0x8d 176 r.Type = ld.R_PCREL 177 return 178 } 179 180 addgotsym(ld.Ctxt, targ) 181 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 182 r.Add += int64(targ.Got) 183 r.Type = ld.R_PCREL 184 return 185 } 186 187 // Handle references to ELF symbols from our own object files. 188 if targ.Type != ld.SDYNIMPORT { 189 return 190 } 191 192 switch r.Type { 193 case ld.R_CALL, 194 ld.R_PCREL: 195 addpltsym(ld.Ctxt, targ) 196 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 197 r.Add = int64(targ.Plt) 198 return 199 200 case ld.R_ADDR: 201 if s.Type != ld.SDATA { 202 break 203 } 204 if ld.Iself { 205 adddynsym(ld.Ctxt, targ) 206 rel := ld.Linklookup(ld.Ctxt, ".rel", 0) 207 ld.Addaddrplus(ld.Ctxt, rel, s, int64(r.Off)) 208 ld.Adduint32(ld.Ctxt, rel, ld.ELF32_R_INFO(uint32(targ.Dynid), ld.R_386_32)) 209 r.Type = ld.R_CONST // write r->add during relocsym 210 r.Sym = nil 211 return 212 } 213 214 if ld.HEADTYPE == ld.Hdarwin && s.Size == PtrSize && r.Off == 0 { 215 // Mach-O relocations are a royal pain to lay out. 216 // They use a compact stateful bytecode representation 217 // that is too much bother to deal with. 218 // Instead, interpret the C declaration 219 // void *_Cvar_stderr = &stderr; 220 // as making _Cvar_stderr the name of a GOT entry 221 // for stderr. This is separate from the usual GOT entry, 222 // just in case the C code assigns to the variable, 223 // and of course it only works for single pointers, 224 // but we only need to support cgo and that's all it needs. 225 adddynsym(ld.Ctxt, targ) 226 227 got := ld.Linklookup(ld.Ctxt, ".got", 0) 228 s.Type = got.Type | ld.SSUB 229 s.Outer = got 230 s.Sub = got.Sub 231 got.Sub = s 232 s.Value = got.Size 233 ld.Adduint32(ld.Ctxt, got, 0) 234 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.got", 0), uint32(targ.Dynid)) 235 r.Type = 256 // ignore during relocsym 236 return 237 } 238 239 if ld.HEADTYPE == ld.Hwindows && s.Size == PtrSize { 240 // nothing to do, the relocation will be laid out in pereloc1 241 return 242 } 243 } 244 245 ld.Ctxt.Cursym = s 246 ld.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type) 247 } 248 249 func elfreloc1(r *ld.Reloc, sectoff int64) int { 250 ld.Thearch.Lput(uint32(sectoff)) 251 252 elfsym := r.Xsym.Elfsym 253 switch r.Type { 254 default: 255 return -1 256 257 case ld.R_ADDR: 258 if r.Siz == 4 { 259 ld.Thearch.Lput(ld.R_386_32 | uint32(elfsym)<<8) 260 } else { 261 return -1 262 } 263 264 case ld.R_CALL, 265 ld.R_PCREL: 266 if r.Siz == 4 { 267 ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8) 268 } else { 269 return -1 270 } 271 272 case ld.R_TLS_LE, 273 ld.R_TLS_IE: 274 if r.Siz == 4 { 275 ld.Thearch.Lput(ld.R_386_TLS_LE | uint32(elfsym)<<8) 276 } else { 277 return -1 278 } 279 } 280 281 return 0 282 } 283 284 func machoreloc1(r *ld.Reloc, sectoff int64) int { 285 var v uint32 286 287 rs := r.Xsym 288 289 if rs.Type == ld.SHOSTOBJ { 290 if rs.Dynid < 0 { 291 ld.Diag("reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type) 292 return -1 293 } 294 295 v = uint32(rs.Dynid) 296 v |= 1 << 27 // external relocation 297 } else { 298 v = uint32((rs.Sect.(*ld.Section)).Extnum) 299 if v == 0 { 300 ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, (rs.Sect.(*ld.Section)).Name, rs.Type) 301 return -1 302 } 303 } 304 305 switch r.Type { 306 default: 307 return -1 308 309 case ld.R_ADDR: 310 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 311 312 case ld.R_CALL, 313 ld.R_PCREL: 314 v |= 1 << 24 // pc-relative bit 315 v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28 316 } 317 318 switch r.Siz { 319 default: 320 return -1 321 322 case 1: 323 v |= 0 << 25 324 325 case 2: 326 v |= 1 << 25 327 328 case 4: 329 v |= 2 << 25 330 331 case 8: 332 v |= 3 << 25 333 } 334 335 ld.Thearch.Lput(uint32(sectoff)) 336 ld.Thearch.Lput(v) 337 return 0 338 } 339 340 func pereloc1(r *ld.Reloc, sectoff int64) bool { 341 var v uint32 342 343 rs := r.Xsym 344 345 if rs.Dynid < 0 { 346 ld.Diag("reloc %d to non-coff symbol %s type=%d", r.Type, rs.Name, rs.Type) 347 return false 348 } 349 350 ld.Thearch.Lput(uint32(sectoff)) 351 ld.Thearch.Lput(uint32(rs.Dynid)) 352 353 switch r.Type { 354 default: 355 return false 356 357 case ld.R_ADDR: 358 v = ld.IMAGE_REL_I386_DIR32 359 360 case ld.R_CALL, 361 ld.R_PCREL: 362 v = ld.IMAGE_REL_I386_REL32 363 } 364 365 ld.Thearch.Wput(uint16(v)) 366 367 return true 368 } 369 370 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { 371 if ld.Linkmode == ld.LinkExternal { 372 return -1 373 } 374 switch r.Type { 375 case ld.R_CONST: 376 *val = r.Add 377 return 0 378 379 case ld.R_GOTOFF: 380 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0)) 381 return 0 382 } 383 384 return -1 385 } 386 387 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 { 388 log.Fatalf("unexpected relocation variant") 389 return t 390 } 391 392 func elfsetupplt() { 393 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 394 got := ld.Linklookup(ld.Ctxt, ".got.plt", 0) 395 if plt.Size == 0 { 396 // pushl got+4 397 ld.Adduint8(ld.Ctxt, plt, 0xff) 398 399 ld.Adduint8(ld.Ctxt, plt, 0x35) 400 ld.Addaddrplus(ld.Ctxt, plt, got, 4) 401 402 // jmp *got+8 403 ld.Adduint8(ld.Ctxt, plt, 0xff) 404 405 ld.Adduint8(ld.Ctxt, plt, 0x25) 406 ld.Addaddrplus(ld.Ctxt, plt, got, 8) 407 408 // zero pad 409 ld.Adduint32(ld.Ctxt, plt, 0) 410 411 // assume got->size == 0 too 412 ld.Addaddrplus(ld.Ctxt, got, ld.Linklookup(ld.Ctxt, ".dynamic", 0), 0) 413 414 ld.Adduint32(ld.Ctxt, got, 0) 415 ld.Adduint32(ld.Ctxt, got, 0) 416 } 417 } 418 419 func addpltsym(ctxt *ld.Link, s *ld.LSym) { 420 if s.Plt >= 0 { 421 return 422 } 423 424 adddynsym(ctxt, s) 425 426 if ld.Iself { 427 plt := ld.Linklookup(ctxt, ".plt", 0) 428 got := ld.Linklookup(ctxt, ".got.plt", 0) 429 rel := ld.Linklookup(ctxt, ".rel.plt", 0) 430 if plt.Size == 0 { 431 elfsetupplt() 432 } 433 434 // jmpq *got+size 435 ld.Adduint8(ctxt, plt, 0xff) 436 437 ld.Adduint8(ctxt, plt, 0x25) 438 ld.Addaddrplus(ctxt, plt, got, got.Size) 439 440 // add to got: pointer to current pos in plt 441 ld.Addaddrplus(ctxt, got, plt, plt.Size) 442 443 // pushl $x 444 ld.Adduint8(ctxt, plt, 0x68) 445 446 ld.Adduint32(ctxt, plt, uint32(rel.Size)) 447 448 // jmp .plt 449 ld.Adduint8(ctxt, plt, 0xe9) 450 451 ld.Adduint32(ctxt, plt, uint32(-(plt.Size + 4))) 452 453 // rel 454 ld.Addaddrplus(ctxt, rel, got, got.Size-4) 455 456 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT)) 457 458 s.Plt = int32(plt.Size - 16) 459 } else if ld.HEADTYPE == ld.Hdarwin { 460 // Same laziness as in 6l. 461 462 plt := ld.Linklookup(ctxt, ".plt", 0) 463 464 addgotsym(ctxt, s) 465 466 ld.Adduint32(ctxt, ld.Linklookup(ctxt, ".linkedit.plt", 0), uint32(s.Dynid)) 467 468 // jmpq *got+size(IP) 469 s.Plt = int32(plt.Size) 470 471 ld.Adduint8(ctxt, plt, 0xff) 472 ld.Adduint8(ctxt, plt, 0x25) 473 ld.Addaddrplus(ctxt, plt, ld.Linklookup(ctxt, ".got", 0), int64(s.Got)) 474 } else { 475 ld.Diag("addpltsym: unsupported binary format") 476 } 477 } 478 479 func addgotsym(ctxt *ld.Link, s *ld.LSym) { 480 if s.Got >= 0 { 481 return 482 } 483 484 adddynsym(ctxt, s) 485 got := ld.Linklookup(ctxt, ".got", 0) 486 s.Got = int32(got.Size) 487 ld.Adduint32(ctxt, got, 0) 488 489 if ld.Iself { 490 rel := ld.Linklookup(ctxt, ".rel", 0) 491 ld.Addaddrplus(ctxt, rel, got, int64(s.Got)) 492 ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_GLOB_DAT)) 493 } else if ld.HEADTYPE == ld.Hdarwin { 494 ld.Adduint32(ctxt, ld.Linklookup(ctxt, ".linkedit.got", 0), uint32(s.Dynid)) 495 } else { 496 ld.Diag("addgotsym: unsupported binary format") 497 } 498 } 499 500 func adddynsym(ctxt *ld.Link, s *ld.LSym) { 501 if s.Dynid >= 0 { 502 return 503 } 504 505 if ld.Iself { 506 s.Dynid = int32(ld.Nelfsym) 507 ld.Nelfsym++ 508 509 d := ld.Linklookup(ctxt, ".dynsym", 0) 510 511 /* name */ 512 name := s.Extname 513 514 ld.Adduint32(ctxt, d, uint32(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), name))) 515 516 /* value */ 517 if s.Type == ld.SDYNIMPORT { 518 ld.Adduint32(ctxt, d, 0) 519 } else { 520 ld.Addaddr(ctxt, d, s) 521 } 522 523 /* size */ 524 ld.Adduint32(ctxt, d, 0) 525 526 /* type */ 527 t := ld.STB_GLOBAL << 4 528 529 if s.Cgoexport != 0 && s.Type&ld.SMASK == ld.STEXT { 530 t |= ld.STT_FUNC 531 } else { 532 t |= ld.STT_OBJECT 533 } 534 ld.Adduint8(ctxt, d, uint8(t)) 535 ld.Adduint8(ctxt, d, 0) 536 537 /* shndx */ 538 if s.Type == ld.SDYNIMPORT { 539 ld.Adduint16(ctxt, d, ld.SHN_UNDEF) 540 } else { 541 ld.Adduint16(ctxt, d, 1) 542 } 543 } else if ld.HEADTYPE == ld.Hdarwin { 544 ld.Diag("adddynsym: missed symbol %s (%s)", s.Name, s.Extname) 545 } else if ld.HEADTYPE == ld.Hwindows { 546 } else // already taken care of 547 { 548 ld.Diag("adddynsym: unsupported binary format") 549 } 550 } 551 552 func adddynlib(lib string) { 553 if needlib(lib) == 0 { 554 return 555 } 556 557 if ld.Iself { 558 s := ld.Linklookup(ld.Ctxt, ".dynstr", 0) 559 if s.Size == 0 { 560 ld.Addstring(s, "") 561 } 562 ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib))) 563 } else if ld.HEADTYPE == ld.Hdarwin { 564 ld.Machoadddynlib(lib) 565 } else if ld.HEADTYPE != ld.Hwindows { 566 ld.Diag("adddynlib: unsupported binary format") 567 } 568 } 569 570 func asmb() { 571 if ld.Debug['v'] != 0 { 572 fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime()) 573 } 574 ld.Bflush(&ld.Bso) 575 576 if ld.Iself { 577 ld.Asmbelfsetup() 578 } 579 580 sect := ld.Segtext.Sect 581 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 582 ld.Codeblk(int64(sect.Vaddr), int64(sect.Length)) 583 for sect = sect.Next; sect != nil; sect = sect.Next { 584 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 585 ld.Datblk(int64(sect.Vaddr), int64(sect.Length)) 586 } 587 588 if ld.Segrodata.Filelen > 0 { 589 if ld.Debug['v'] != 0 { 590 fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime()) 591 } 592 ld.Bflush(&ld.Bso) 593 594 ld.Cseek(int64(ld.Segrodata.Fileoff)) 595 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 596 } 597 598 if ld.Debug['v'] != 0 { 599 fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime()) 600 } 601 ld.Bflush(&ld.Bso) 602 603 ld.Cseek(int64(ld.Segdata.Fileoff)) 604 ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 605 606 machlink := uint32(0) 607 if ld.HEADTYPE == ld.Hdarwin { 608 if ld.Debug['v'] != 0 { 609 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 610 } 611 612 dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) 613 ld.Cseek(int64(dwarfoff)) 614 615 ld.Segdwarf.Fileoff = uint64(ld.Cpos()) 616 ld.Dwarfemitdebugsections() 617 ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff 618 619 machlink = uint32(ld.Domacholink()) 620 } 621 622 ld.Symsize = 0 623 ld.Spsize = 0 624 ld.Lcsize = 0 625 symo := uint32(0) 626 if ld.Debug['s'] == 0 { 627 // TODO: rationalize 628 if ld.Debug['v'] != 0 { 629 fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime()) 630 } 631 ld.Bflush(&ld.Bso) 632 switch ld.HEADTYPE { 633 default: 634 if ld.Iself { 635 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 636 symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND))) 637 } 638 639 case ld.Hplan9: 640 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 641 642 case ld.Hdarwin: 643 symo = uint32(ld.Segdata.Fileoff + uint64(ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) + uint64(machlink)) 644 645 case ld.Hwindows: 646 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 647 symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN)) 648 } 649 650 ld.Cseek(int64(symo)) 651 switch ld.HEADTYPE { 652 default: 653 if ld.Iself { 654 if ld.Debug['v'] != 0 { 655 fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime()) 656 } 657 ld.Asmelfsym() 658 ld.Cflush() 659 ld.Cwrite(ld.Elfstrdat) 660 661 if ld.Debug['v'] != 0 { 662 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 663 } 664 ld.Dwarfemitdebugsections() 665 666 if ld.Linkmode == ld.LinkExternal { 667 ld.Elfemitreloc() 668 } 669 } 670 671 case ld.Hplan9: 672 ld.Asmplan9sym() 673 ld.Cflush() 674 675 sym := ld.Linklookup(ld.Ctxt, "pclntab", 0) 676 if sym != nil { 677 ld.Lcsize = int32(len(sym.P)) 678 for i := 0; int32(i) < ld.Lcsize; i++ { 679 ld.Cput(uint8(sym.P[i])) 680 } 681 682 ld.Cflush() 683 } 684 685 case ld.Hwindows: 686 if ld.Debug['v'] != 0 { 687 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 688 } 689 ld.Dwarfemitdebugsections() 690 691 case ld.Hdarwin: 692 if ld.Linkmode == ld.LinkExternal { 693 ld.Machoemitreloc() 694 } 695 } 696 } 697 698 if ld.Debug['v'] != 0 { 699 fmt.Fprintf(&ld.Bso, "%5.2f headr\n", obj.Cputime()) 700 } 701 ld.Bflush(&ld.Bso) 702 ld.Cseek(0) 703 switch ld.HEADTYPE { 704 default: 705 case ld.Hplan9: /* plan9 */ 706 magic := int32(4*11*11 + 7) 707 708 ld.Lputb(uint32(magic)) /* magic */ 709 ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */ 710 ld.Lputb(uint32(ld.Segdata.Filelen)) 711 ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 712 ld.Lputb(uint32(ld.Symsize)) /* nsyms */ 713 ld.Lputb(uint32(ld.Entryvalue())) /* va of entry */ 714 ld.Lputb(uint32(ld.Spsize)) /* sp offsets */ 715 ld.Lputb(uint32(ld.Lcsize)) /* line offsets */ 716 717 case ld.Hdarwin: 718 ld.Asmbmacho() 719 720 case ld.Hlinux, 721 ld.Hfreebsd, 722 ld.Hnetbsd, 723 ld.Hopenbsd, 724 ld.Hnacl: 725 ld.Asmbelf(int64(symo)) 726 727 case ld.Hwindows: 728 ld.Asmbpe() 729 } 730 731 ld.Cflush() 732 }