rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/cmd/6l/asm.go (about) 1 // Inferno utils/6l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/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 PADDR(x uint32) uint32 { 41 return x &^ 0x80000000 42 } 43 44 var zeroes string 45 46 func needlib(name string) int { 47 if name[0] == '\x00' { 48 return 0 49 } 50 51 /* reuse hash code in symbol table */ 52 p := fmt.Sprintf(".elfload.%s", name) 53 54 s := ld.Linklookup(ld.Ctxt, p, 0) 55 56 if s.Type == 0 { 57 s.Type = 100 // avoid SDATA, etc. 58 return 1 59 } 60 61 return 0 62 } 63 64 func Addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) int64 { 65 s.Reachable = true 66 i := s.Size 67 s.Size += 4 68 ld.Symgrow(ctxt, s, s.Size) 69 r := ld.Addrel(s) 70 r.Sym = t 71 r.Off = int32(i) 72 r.Type = ld.R_CALL 73 r.Siz = 4 74 return i + int64(r.Siz) 75 } 76 77 func gentext() { 78 if !ld.DynlinkingGo() { 79 return 80 } 81 addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0) 82 if addmoduledata.Type == ld.STEXT { 83 // we're linking a module containing the runtime -> no need for 84 // an init function 85 return 86 } 87 addmoduledata.Reachable = true 88 initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0) 89 initfunc.Type = ld.STEXT 90 initfunc.Local = true 91 initfunc.Reachable = true 92 o := func(op ...uint8) { 93 for _, op1 := range op { 94 ld.Adduint8(ld.Ctxt, initfunc, op1) 95 } 96 } 97 // 0000000000000000 <local.dso_init>: 98 // 0: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 7 <local.dso_init+0x7> 99 // 3: R_X86_64_PC32 runtime.firstmoduledata-0x4 100 o(0x48, 0x8d, 0x3d) 101 ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Linklookup(ld.Ctxt, "runtime.firstmoduledata", 0), 0) 102 // 7: e8 00 00 00 00 callq c <local.dso_init+0xc> 103 // 8: R_X86_64_PLT32 runtime.addmoduledata-0x4 104 o(0xe8) 105 Addcall(ld.Ctxt, initfunc, addmoduledata) 106 // c: c3 retq 107 o(0xc3) 108 if ld.Ctxt.Etextp != nil { 109 ld.Ctxt.Etextp.Next = initfunc 110 } else { 111 ld.Ctxt.Textp = initfunc 112 } 113 ld.Ctxt.Etextp = initfunc 114 initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0) 115 initarray_entry.Reachable = true 116 initarray_entry.Local = true 117 initarray_entry.Type = ld.SINITARR 118 ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) 119 } 120 121 func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { 122 ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off)) 123 ld.Adduint64(ld.Ctxt, rela, ld.R_X86_64_RELATIVE) 124 ld.Addaddrplus(ld.Ctxt, rela, r.Sym, r.Add) // Addend 125 } 126 127 func adddynrel(s *ld.LSym, r *ld.Reloc) { 128 targ := r.Sym 129 ld.Ctxt.Cursym = s 130 131 switch r.Type { 132 default: 133 if r.Type >= 256 { 134 ld.Diag("unexpected relocation type %d", r.Type) 135 return 136 } 137 138 // Handle relocations found in ELF object files. 139 case 256 + ld.R_X86_64_PC32: 140 if targ.Type == ld.SDYNIMPORT { 141 ld.Diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name) 142 } 143 if targ.Type == 0 || targ.Type == ld.SXREF { 144 ld.Diag("unknown symbol %s in pcrel", targ.Name) 145 } 146 r.Type = ld.R_PCREL 147 r.Add += 4 148 return 149 150 case 256 + ld.R_X86_64_PLT32: 151 r.Type = ld.R_PCREL 152 r.Add += 4 153 if targ.Type == ld.SDYNIMPORT { 154 addpltsym(targ) 155 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 156 r.Add += int64(targ.Plt) 157 } 158 159 return 160 161 case 256 + ld.R_X86_64_GOTPCREL: 162 if targ.Type != ld.SDYNIMPORT { 163 // have symbol 164 if r.Off >= 2 && s.P[r.Off-2] == 0x8b { 165 // turn MOVQ of GOT entry into LEAQ of symbol itself 166 s.P[r.Off-2] = 0x8d 167 168 r.Type = ld.R_PCREL 169 r.Add += 4 170 return 171 } 172 } 173 174 // fall back to using GOT and hope for the best (CMOV*) 175 // TODO: just needs relocation, no need to put in .dynsym 176 addgotsym(targ) 177 178 r.Type = ld.R_PCREL 179 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 180 r.Add += 4 181 r.Add += int64(targ.Got) 182 return 183 184 case 256 + ld.R_X86_64_64: 185 if targ.Type == ld.SDYNIMPORT { 186 ld.Diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name) 187 } 188 r.Type = ld.R_ADDR 189 return 190 191 // Handle relocations found in Mach-O object files. 192 case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0, 193 512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0, 194 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0: 195 // TODO: What is the difference between all these? 196 r.Type = ld.R_ADDR 197 198 if targ.Type == ld.SDYNIMPORT { 199 ld.Diag("unexpected reloc for dynamic symbol %s", targ.Name) 200 } 201 return 202 203 case 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1: 204 if targ.Type == ld.SDYNIMPORT { 205 addpltsym(targ) 206 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 207 r.Add = int64(targ.Plt) 208 r.Type = ld.R_PCREL 209 return 210 } 211 fallthrough 212 213 // fall through 214 case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1, 215 512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1, 216 512 + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1, 217 512 + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1, 218 512 + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1: 219 r.Type = ld.R_PCREL 220 221 if targ.Type == ld.SDYNIMPORT { 222 ld.Diag("unexpected pc-relative reloc for dynamic symbol %s", targ.Name) 223 } 224 return 225 226 case 512 + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1: 227 if targ.Type != ld.SDYNIMPORT { 228 // have symbol 229 // turn MOVQ of GOT entry into LEAQ of symbol itself 230 if r.Off < 2 || s.P[r.Off-2] != 0x8b { 231 ld.Diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ.Name) 232 return 233 } 234 235 s.P[r.Off-2] = 0x8d 236 r.Type = ld.R_PCREL 237 return 238 } 239 fallthrough 240 241 // fall through 242 case 512 + ld.MACHO_X86_64_RELOC_GOT*2 + 1: 243 if targ.Type != ld.SDYNIMPORT { 244 ld.Diag("unexpected GOT reloc for non-dynamic symbol %s", targ.Name) 245 } 246 addgotsym(targ) 247 r.Type = ld.R_PCREL 248 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 249 r.Add += int64(targ.Got) 250 return 251 } 252 253 // Handle references to ELF symbols from our own object files. 254 if targ.Type != ld.SDYNIMPORT { 255 return 256 } 257 258 switch r.Type { 259 case ld.R_CALL, 260 ld.R_PCREL: 261 if ld.HEADTYPE == ld.Hwindows { 262 // nothing to do, the relocation will be laid out in pereloc1 263 return 264 } else { 265 // for both ELF and Mach-O 266 addpltsym(targ) 267 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 268 r.Add = int64(targ.Plt) 269 return 270 } 271 272 case ld.R_ADDR: 273 if s.Type == ld.STEXT && ld.Iself { 274 // The code is asking for the address of an external 275 // function. We provide it with the address of the 276 // correspondent GOT symbol. 277 addgotsym(targ) 278 279 r.Sym = ld.Linklookup(ld.Ctxt, ".got", 0) 280 r.Add += int64(targ.Got) 281 return 282 } 283 284 if s.Type != ld.SDATA { 285 break 286 } 287 if ld.Iself { 288 adddynsym(ld.Ctxt, targ) 289 rela := ld.Linklookup(ld.Ctxt, ".rela", 0) 290 ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off)) 291 if r.Siz == 8 { 292 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_X86_64_64)) 293 } else { 294 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_X86_64_32)) 295 } 296 ld.Adduint64(ld.Ctxt, rela, uint64(r.Add)) 297 r.Type = 256 // ignore during relocsym 298 return 299 } 300 301 if ld.HEADTYPE == ld.Hdarwin && s.Size == int64(ld.Thearch.Ptrsize) && r.Off == 0 { 302 // Mach-O relocations are a royal pain to lay out. 303 // They use a compact stateful bytecode representation 304 // that is too much bother to deal with. 305 // Instead, interpret the C declaration 306 // void *_Cvar_stderr = &stderr; 307 // as making _Cvar_stderr the name of a GOT entry 308 // for stderr. This is separate from the usual GOT entry, 309 // just in case the C code assigns to the variable, 310 // and of course it only works for single pointers, 311 // but we only need to support cgo and that's all it needs. 312 adddynsym(ld.Ctxt, targ) 313 314 got := ld.Linklookup(ld.Ctxt, ".got", 0) 315 s.Type = got.Type | ld.SSUB 316 s.Outer = got 317 s.Sub = got.Sub 318 got.Sub = s 319 s.Value = got.Size 320 ld.Adduint64(ld.Ctxt, got, 0) 321 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.got", 0), uint32(targ.Dynid)) 322 r.Type = 256 // ignore during relocsym 323 return 324 } 325 326 if ld.HEADTYPE == ld.Hwindows { 327 // nothing to do, the relocation will be laid out in pereloc1 328 return 329 } 330 } 331 332 ld.Ctxt.Cursym = s 333 ld.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type) 334 } 335 336 func elfreloc1(r *ld.Reloc, sectoff int64) int { 337 ld.Thearch.Vput(uint64(sectoff)) 338 339 elfsym := r.Xsym.Elfsym 340 switch r.Type { 341 default: 342 return -1 343 344 case ld.R_ADDR: 345 if r.Siz == 4 { 346 ld.Thearch.Vput(ld.R_X86_64_32 | uint64(elfsym)<<32) 347 } else if r.Siz == 8 { 348 ld.Thearch.Vput(ld.R_X86_64_64 | uint64(elfsym)<<32) 349 } else { 350 return -1 351 } 352 353 case ld.R_TLS_LE: 354 if r.Siz == 4 { 355 ld.Thearch.Vput(ld.R_X86_64_TPOFF32 | uint64(elfsym)<<32) 356 } else { 357 return -1 358 } 359 360 case ld.R_TLS_IE: 361 if r.Siz == 4 { 362 ld.Thearch.Vput(ld.R_X86_64_GOTTPOFF | uint64(elfsym)<<32) 363 } else { 364 return -1 365 } 366 367 case ld.R_CALL: 368 if r.Siz == 4 { 369 if r.Xsym.Type == ld.SDYNIMPORT { 370 if ld.DynlinkingGo() { 371 ld.Thearch.Vput(ld.R_X86_64_PLT32 | uint64(elfsym)<<32) 372 } else { 373 ld.Thearch.Vput(ld.R_X86_64_GOTPCREL | uint64(elfsym)<<32) 374 } 375 } else { 376 ld.Thearch.Vput(ld.R_X86_64_PC32 | uint64(elfsym)<<32) 377 } 378 } else { 379 return -1 380 } 381 382 case ld.R_PCREL: 383 if r.Siz == 4 { 384 ld.Thearch.Vput(ld.R_X86_64_PC32 | uint64(elfsym)<<32) 385 } else { 386 return -1 387 } 388 389 case ld.R_GOTPCREL: 390 if r.Siz == 4 { 391 ld.Thearch.Vput(ld.R_X86_64_GOTPCREL | uint64(elfsym)<<32) 392 } else { 393 return -1 394 } 395 396 case ld.R_TLS: 397 if r.Siz == 4 { 398 if ld.Buildmode == ld.BuildmodeCShared { 399 ld.Thearch.Vput(ld.R_X86_64_GOTTPOFF | uint64(elfsym)<<32) 400 } else { 401 ld.Thearch.Vput(ld.R_X86_64_TPOFF32 | uint64(elfsym)<<32) 402 } 403 } else { 404 return -1 405 } 406 } 407 408 ld.Thearch.Vput(uint64(r.Xadd)) 409 return 0 410 } 411 412 func machoreloc1(r *ld.Reloc, sectoff int64) int { 413 var v uint32 414 415 rs := r.Xsym 416 417 if rs.Type == ld.SHOSTOBJ || r.Type == ld.R_PCREL { 418 if rs.Dynid < 0 { 419 ld.Diag("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.(*ld.Section)).Extnum) 427 if v == 0 { 428 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) 429 return -1 430 } 431 } 432 433 switch r.Type { 434 default: 435 return -1 436 437 case ld.R_ADDR: 438 v |= ld.MACHO_X86_64_RELOC_UNSIGNED << 28 439 440 case ld.R_CALL: 441 v |= 1 << 24 // pc-relative bit 442 v |= ld.MACHO_X86_64_RELOC_BRANCH << 28 443 444 // NOTE: Only works with 'external' relocation. Forced above. 445 case ld.R_PCREL: 446 v |= 1 << 24 // pc-relative bit 447 v |= ld.MACHO_X86_64_RELOC_SIGNED << 28 448 } 449 450 switch r.Siz { 451 default: 452 return -1 453 454 case 1: 455 v |= 0 << 25 456 457 case 2: 458 v |= 1 << 25 459 460 case 4: 461 v |= 2 << 25 462 463 case 8: 464 v |= 3 << 25 465 } 466 467 ld.Thearch.Lput(uint32(sectoff)) 468 ld.Thearch.Lput(v) 469 return 0 470 } 471 472 func pereloc1(r *ld.Reloc, sectoff int64) bool { 473 var v uint32 474 475 rs := r.Xsym 476 477 if rs.Dynid < 0 { 478 ld.Diag("reloc %d to non-coff symbol %s type=%d", r.Type, rs.Name, rs.Type) 479 return false 480 } 481 482 ld.Thearch.Lput(uint32(sectoff)) 483 ld.Thearch.Lput(uint32(rs.Dynid)) 484 485 switch r.Type { 486 default: 487 return false 488 489 case ld.R_ADDR: 490 if r.Siz == 8 { 491 v = ld.IMAGE_REL_AMD64_ADDR64 492 } else { 493 v = ld.IMAGE_REL_AMD64_ADDR32 494 } 495 496 case ld.R_CALL, 497 ld.R_PCREL: 498 v = ld.IMAGE_REL_AMD64_REL32 499 } 500 501 ld.Thearch.Wput(uint16(v)) 502 503 return true 504 } 505 506 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { 507 return -1 508 } 509 510 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 { 511 log.Fatalf("unexpected relocation variant") 512 return t 513 } 514 515 func elfsetupplt() { 516 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 517 got := ld.Linklookup(ld.Ctxt, ".got.plt", 0) 518 if plt.Size == 0 { 519 // pushq got+8(IP) 520 ld.Adduint8(ld.Ctxt, plt, 0xff) 521 522 ld.Adduint8(ld.Ctxt, plt, 0x35) 523 ld.Addpcrelplus(ld.Ctxt, plt, got, 8) 524 525 // jmpq got+16(IP) 526 ld.Adduint8(ld.Ctxt, plt, 0xff) 527 528 ld.Adduint8(ld.Ctxt, plt, 0x25) 529 ld.Addpcrelplus(ld.Ctxt, plt, got, 16) 530 531 // nopl 0(AX) 532 ld.Adduint32(ld.Ctxt, plt, 0x00401f0f) 533 534 // assume got->size == 0 too 535 ld.Addaddrplus(ld.Ctxt, got, ld.Linklookup(ld.Ctxt, ".dynamic", 0), 0) 536 537 ld.Adduint64(ld.Ctxt, got, 0) 538 ld.Adduint64(ld.Ctxt, got, 0) 539 } 540 } 541 542 func addpltsym(s *ld.LSym) { 543 if s.Plt >= 0 { 544 return 545 } 546 547 adddynsym(ld.Ctxt, s) 548 549 if ld.Iself { 550 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 551 got := ld.Linklookup(ld.Ctxt, ".got.plt", 0) 552 rela := ld.Linklookup(ld.Ctxt, ".rela.plt", 0) 553 if plt.Size == 0 { 554 elfsetupplt() 555 } 556 557 // jmpq *got+size(IP) 558 ld.Adduint8(ld.Ctxt, plt, 0xff) 559 560 ld.Adduint8(ld.Ctxt, plt, 0x25) 561 ld.Addpcrelplus(ld.Ctxt, plt, got, got.Size) 562 563 // add to got: pointer to current pos in plt 564 ld.Addaddrplus(ld.Ctxt, got, plt, plt.Size) 565 566 // pushq $x 567 ld.Adduint8(ld.Ctxt, plt, 0x68) 568 569 ld.Adduint32(ld.Ctxt, plt, uint32((got.Size-24-8)/8)) 570 571 // jmpq .plt 572 ld.Adduint8(ld.Ctxt, plt, 0xe9) 573 574 ld.Adduint32(ld.Ctxt, plt, uint32(-(plt.Size + 4))) 575 576 // rela 577 ld.Addaddrplus(ld.Ctxt, rela, got, got.Size-8) 578 579 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_X86_64_JMP_SLOT)) 580 ld.Adduint64(ld.Ctxt, rela, 0) 581 582 s.Plt = int32(plt.Size - 16) 583 } else if ld.HEADTYPE == ld.Hdarwin { 584 // To do lazy symbol lookup right, we're supposed 585 // to tell the dynamic loader which library each 586 // symbol comes from and format the link info 587 // section just so. I'm too lazy (ha!) to do that 588 // so for now we'll just use non-lazy pointers, 589 // which don't need to be told which library to use. 590 // 591 // http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html 592 // has details about what we're avoiding. 593 594 addgotsym(s) 595 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 596 597 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.plt", 0), uint32(s.Dynid)) 598 599 // jmpq *got+size(IP) 600 s.Plt = int32(plt.Size) 601 602 ld.Adduint8(ld.Ctxt, plt, 0xff) 603 ld.Adduint8(ld.Ctxt, plt, 0x25) 604 ld.Addpcrelplus(ld.Ctxt, plt, ld.Linklookup(ld.Ctxt, ".got", 0), int64(s.Got)) 605 } else { 606 ld.Diag("addpltsym: unsupported binary format") 607 } 608 } 609 610 func addgotsym(s *ld.LSym) { 611 if s.Got >= 0 { 612 return 613 } 614 615 adddynsym(ld.Ctxt, s) 616 got := ld.Linklookup(ld.Ctxt, ".got", 0) 617 s.Got = int32(got.Size) 618 ld.Adduint64(ld.Ctxt, got, 0) 619 620 if ld.Iself { 621 rela := ld.Linklookup(ld.Ctxt, ".rela", 0) 622 ld.Addaddrplus(ld.Ctxt, rela, got, int64(s.Got)) 623 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_X86_64_GLOB_DAT)) 624 ld.Adduint64(ld.Ctxt, rela, 0) 625 } else if ld.HEADTYPE == ld.Hdarwin { 626 ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.got", 0), uint32(s.Dynid)) 627 } else { 628 ld.Diag("addgotsym: unsupported binary format") 629 } 630 } 631 632 func adddynsym(ctxt *ld.Link, s *ld.LSym) { 633 if s.Dynid >= 0 { 634 return 635 } 636 637 if ld.Iself { 638 s.Dynid = int32(ld.Nelfsym) 639 ld.Nelfsym++ 640 641 d := ld.Linklookup(ctxt, ".dynsym", 0) 642 643 name := s.Extname 644 ld.Adduint32(ctxt, d, uint32(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), name))) 645 646 /* type */ 647 t := ld.STB_GLOBAL << 4 648 649 if s.Cgoexport != 0 && s.Type&ld.SMASK == ld.STEXT { 650 t |= ld.STT_FUNC 651 } else { 652 t |= ld.STT_OBJECT 653 } 654 ld.Adduint8(ctxt, d, uint8(t)) 655 656 /* reserved */ 657 ld.Adduint8(ctxt, d, 0) 658 659 /* section where symbol is defined */ 660 if s.Type == ld.SDYNIMPORT { 661 ld.Adduint16(ctxt, d, ld.SHN_UNDEF) 662 } else { 663 ld.Adduint16(ctxt, d, 1) 664 } 665 666 /* value */ 667 if s.Type == ld.SDYNIMPORT { 668 ld.Adduint64(ctxt, d, 0) 669 } else { 670 ld.Addaddr(ctxt, d, s) 671 } 672 673 /* size of object */ 674 ld.Adduint64(ctxt, d, uint64(s.Size)) 675 676 if s.Cgoexport&ld.CgoExportDynamic == 0 && s.Dynimplib != "" && needlib(s.Dynimplib) != 0 { 677 ld.Elfwritedynent(ld.Linklookup(ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), s.Dynimplib))) 678 } 679 } else if ld.HEADTYPE == ld.Hdarwin { 680 ld.Diag("adddynsym: missed symbol %s (%s)", s.Name, s.Extname) 681 } else if ld.HEADTYPE == ld.Hwindows { 682 } else // already taken care of 683 { 684 ld.Diag("adddynsym: unsupported binary format") 685 } 686 } 687 688 func adddynlib(lib string) { 689 if needlib(lib) == 0 { 690 return 691 } 692 693 if ld.Iself { 694 s := ld.Linklookup(ld.Ctxt, ".dynstr", 0) 695 if s.Size == 0 { 696 ld.Addstring(s, "") 697 } 698 ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib))) 699 } else if ld.HEADTYPE == ld.Hdarwin { 700 ld.Machoadddynlib(lib) 701 } else { 702 ld.Diag("adddynlib: unsupported binary format") 703 } 704 } 705 706 func asmb() { 707 if ld.Debug['v'] != 0 { 708 fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime()) 709 } 710 ld.Bflush(&ld.Bso) 711 712 if ld.Debug['v'] != 0 { 713 fmt.Fprintf(&ld.Bso, "%5.2f codeblk\n", obj.Cputime()) 714 } 715 ld.Bflush(&ld.Bso) 716 717 if ld.Iself { 718 ld.Asmbelfsetup() 719 } 720 721 sect := ld.Segtext.Sect 722 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 723 ld.Codeblk(int64(sect.Vaddr), int64(sect.Length)) 724 for sect = sect.Next; sect != nil; sect = sect.Next { 725 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 726 ld.Datblk(int64(sect.Vaddr), int64(sect.Length)) 727 } 728 729 if ld.Segrodata.Filelen > 0 { 730 if ld.Debug['v'] != 0 { 731 fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime()) 732 } 733 ld.Bflush(&ld.Bso) 734 735 ld.Cseek(int64(ld.Segrodata.Fileoff)) 736 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 737 } 738 739 if ld.Debug['v'] != 0 { 740 fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime()) 741 } 742 ld.Bflush(&ld.Bso) 743 744 ld.Cseek(int64(ld.Segdata.Fileoff)) 745 ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 746 747 machlink := int64(0) 748 if ld.HEADTYPE == ld.Hdarwin { 749 if ld.Debug['v'] != 0 { 750 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 751 } 752 753 dwarfoff := ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) 754 ld.Cseek(dwarfoff) 755 756 ld.Segdwarf.Fileoff = uint64(ld.Cpos()) 757 ld.Dwarfemitdebugsections() 758 ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff 759 760 machlink = ld.Domacholink() 761 } 762 763 switch ld.HEADTYPE { 764 default: 765 ld.Diag("unknown header type %d", ld.HEADTYPE) 766 fallthrough 767 768 case ld.Hplan9, 769 ld.Helf: 770 break 771 772 case ld.Hdarwin: 773 ld.Debug['8'] = 1 /* 64-bit addresses */ 774 775 case ld.Hlinux, 776 ld.Hfreebsd, 777 ld.Hnetbsd, 778 ld.Hopenbsd, 779 ld.Hdragonfly, 780 ld.Hsolaris: 781 ld.Debug['8'] = 1 /* 64-bit addresses */ 782 783 case ld.Hnacl, 784 ld.Hwindows: 785 break 786 } 787 788 ld.Symsize = 0 789 ld.Spsize = 0 790 ld.Lcsize = 0 791 symo := int64(0) 792 if ld.Debug['s'] == 0 { 793 if ld.Debug['v'] != 0 { 794 fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime()) 795 } 796 ld.Bflush(&ld.Bso) 797 switch ld.HEADTYPE { 798 default: 799 case ld.Hplan9, 800 ld.Helf: 801 ld.Debug['s'] = 1 802 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) 803 804 case ld.Hdarwin: 805 symo = int64(ld.Segdata.Fileoff + uint64(ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) + uint64(machlink)) 806 807 case ld.Hlinux, 808 ld.Hfreebsd, 809 ld.Hnetbsd, 810 ld.Hopenbsd, 811 ld.Hdragonfly, 812 ld.Hsolaris, 813 ld.Hnacl: 814 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) 815 symo = ld.Rnd(symo, int64(ld.INITRND)) 816 817 case ld.Hwindows: 818 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) 819 symo = ld.Rnd(symo, ld.PEFILEALIGN) 820 } 821 822 ld.Cseek(symo) 823 switch ld.HEADTYPE { 824 default: 825 if ld.Iself { 826 ld.Cseek(symo) 827 ld.Asmelfsym() 828 ld.Cflush() 829 ld.Cwrite(ld.Elfstrdat) 830 831 if ld.Debug['v'] != 0 { 832 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 833 } 834 835 ld.Dwarfemitdebugsections() 836 837 if ld.Linkmode == ld.LinkExternal { 838 ld.Elfemitreloc() 839 } 840 } 841 842 case ld.Hplan9: 843 ld.Asmplan9sym() 844 ld.Cflush() 845 846 sym := ld.Linklookup(ld.Ctxt, "pclntab", 0) 847 if sym != nil { 848 ld.Lcsize = int32(len(sym.P)) 849 for i := 0; int32(i) < ld.Lcsize; i++ { 850 ld.Cput(uint8(sym.P[i])) 851 } 852 853 ld.Cflush() 854 } 855 856 case ld.Hwindows: 857 if ld.Debug['v'] != 0 { 858 fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) 859 } 860 861 ld.Dwarfemitdebugsections() 862 863 case ld.Hdarwin: 864 if ld.Linkmode == ld.LinkExternal { 865 ld.Machoemitreloc() 866 } 867 } 868 } 869 870 if ld.Debug['v'] != 0 { 871 fmt.Fprintf(&ld.Bso, "%5.2f headr\n", obj.Cputime()) 872 } 873 ld.Bflush(&ld.Bso) 874 ld.Cseek(0) 875 switch ld.HEADTYPE { 876 default: 877 case ld.Hplan9: /* plan9 */ 878 magic := int32(4*26*26 + 7) 879 880 magic |= 0x00008000 /* fat header */ 881 ld.Lputb(uint32(magic)) /* magic */ 882 ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */ 883 ld.Lputb(uint32(ld.Segdata.Filelen)) 884 ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 885 ld.Lputb(uint32(ld.Symsize)) /* nsyms */ 886 vl := ld.Entryvalue() 887 ld.Lputb(PADDR(uint32(vl))) /* va of entry */ 888 ld.Lputb(uint32(ld.Spsize)) /* sp offsets */ 889 ld.Lputb(uint32(ld.Lcsize)) /* line offsets */ 890 ld.Vputb(uint64(vl)) /* va of entry */ 891 892 case ld.Hdarwin: 893 ld.Asmbmacho() 894 895 case ld.Hlinux, 896 ld.Hfreebsd, 897 ld.Hnetbsd, 898 ld.Hopenbsd, 899 ld.Hdragonfly, 900 ld.Hsolaris, 901 ld.Hnacl: 902 ld.Asmbelf(symo) 903 904 case ld.Hwindows: 905 ld.Asmbpe() 906 } 907 908 ld.Cflush() 909 }