github.com/jonasi/go@v0.0.0-20150930005915-e78e654c1de0/src/cmd/link/internal/ld/data.go (about) 1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c 3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c 4 // 5 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 6 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 7 // Portions Copyright © 1997-1999 Vita Nuova Limited 8 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 9 // Portions Copyright © 2004,2006 Bruce Ellis 10 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 11 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 12 // Portions Copyright © 2009 The Go Authors. All rights reserved. 13 // 14 // Permission is hereby granted, free of charge, to any person obtaining a copy 15 // of this software and associated documentation files (the "Software"), to deal 16 // in the Software without restriction, including without limitation the rights 17 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 // copies of the Software, and to permit persons to whom the Software is 19 // furnished to do so, subject to the following conditions: 20 // 21 // The above copyright notice and this permission notice shall be included in 22 // all copies or substantial portions of the Software. 23 // 24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 // THE SOFTWARE. 31 32 package ld 33 34 import ( 35 "cmd/internal/gcprog" 36 "cmd/internal/obj" 37 "fmt" 38 "log" 39 "os" 40 "strconv" 41 "strings" 42 ) 43 44 func Symgrow(ctxt *Link, s *LSym, siz int64) { 45 if int64(int(siz)) != siz { 46 log.Fatalf("symgrow size %d too long", siz) 47 } 48 if int64(len(s.P)) >= siz { 49 return 50 } 51 for cap(s.P) < int(siz) { 52 s.P = append(s.P[:len(s.P)], 0) 53 } 54 s.P = s.P[:siz] 55 } 56 57 func Addrel(s *LSym) *Reloc { 58 s.R = append(s.R, Reloc{}) 59 return &s.R[len(s.R)-1] 60 } 61 62 func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 { 63 if s.Type == 0 { 64 s.Type = obj.SDATA 65 } 66 s.Reachable = true 67 if s.Size < off+wid { 68 s.Size = off + wid 69 Symgrow(ctxt, s, s.Size) 70 } 71 72 switch wid { 73 case 1: 74 s.P[off] = uint8(v) 75 case 2: 76 ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(v)) 77 case 4: 78 ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) 79 case 8: 80 ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v)) 81 } 82 83 return off + wid 84 } 85 86 func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 { 87 off := s.Size 88 setuintxx(ctxt, s, off, v, int64(wid)) 89 return off 90 } 91 92 func Adduint8(ctxt *Link, s *LSym, v uint8) int64 { 93 return adduintxx(ctxt, s, uint64(v), 1) 94 } 95 96 func Adduint16(ctxt *Link, s *LSym, v uint16) int64 { 97 return adduintxx(ctxt, s, uint64(v), 2) 98 } 99 100 func Adduint32(ctxt *Link, s *LSym, v uint32) int64 { 101 return adduintxx(ctxt, s, uint64(v), 4) 102 } 103 104 func Adduint64(ctxt *Link, s *LSym, v uint64) int64 { 105 return adduintxx(ctxt, s, v, 8) 106 } 107 108 func adduint(ctxt *Link, s *LSym, v uint64) int64 { 109 return adduintxx(ctxt, s, v, Thearch.Intsize) 110 } 111 112 func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 { 113 return setuintxx(ctxt, s, r, uint64(v), 1) 114 } 115 116 func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 { 117 return setuintxx(ctxt, s, r, uint64(v), 4) 118 } 119 120 func Addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 { 121 if s.Type == 0 { 122 s.Type = obj.SDATA 123 } 124 s.Reachable = true 125 i := s.Size 126 s.Size += int64(ctxt.Arch.Ptrsize) 127 Symgrow(ctxt, s, s.Size) 128 r := Addrel(s) 129 r.Sym = t 130 r.Off = int32(i) 131 r.Siz = uint8(ctxt.Arch.Ptrsize) 132 r.Type = obj.R_ADDR 133 r.Add = add 134 return i + int64(r.Siz) 135 } 136 137 func Addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 { 138 if s.Type == 0 { 139 s.Type = obj.SDATA 140 } 141 s.Reachable = true 142 i := s.Size 143 s.Size += 4 144 Symgrow(ctxt, s, s.Size) 145 r := Addrel(s) 146 r.Sym = t 147 r.Off = int32(i) 148 r.Add = add 149 r.Type = obj.R_PCREL 150 r.Siz = 4 151 return i + int64(r.Siz) 152 } 153 154 func Addaddr(ctxt *Link, s *LSym, t *LSym) int64 { 155 return Addaddrplus(ctxt, s, t, 0) 156 } 157 158 func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 { 159 if s.Type == 0 { 160 s.Type = obj.SDATA 161 } 162 s.Reachable = true 163 if off+int64(ctxt.Arch.Ptrsize) > s.Size { 164 s.Size = off + int64(ctxt.Arch.Ptrsize) 165 Symgrow(ctxt, s, s.Size) 166 } 167 168 r := Addrel(s) 169 r.Sym = t 170 r.Off = int32(off) 171 r.Siz = uint8(ctxt.Arch.Ptrsize) 172 r.Type = obj.R_ADDR 173 r.Add = add 174 return off + int64(r.Siz) 175 } 176 177 func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 { 178 return setaddrplus(ctxt, s, off, t, 0) 179 } 180 181 func addsize(ctxt *Link, s *LSym, t *LSym) int64 { 182 if s.Type == 0 { 183 s.Type = obj.SDATA 184 } 185 s.Reachable = true 186 i := s.Size 187 s.Size += int64(ctxt.Arch.Ptrsize) 188 Symgrow(ctxt, s, s.Size) 189 r := Addrel(s) 190 r.Sym = t 191 r.Off = int32(i) 192 r.Siz = uint8(ctxt.Arch.Ptrsize) 193 r.Type = obj.R_SIZE 194 return i + int64(r.Siz) 195 } 196 197 func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 { 198 if s.Type == 0 { 199 s.Type = obj.SDATA 200 } 201 s.Reachable = true 202 i := s.Size 203 s.Size += 4 204 Symgrow(ctxt, s, s.Size) 205 r := Addrel(s) 206 r.Sym = t 207 r.Off = int32(i) 208 r.Siz = 4 209 r.Type = obj.R_ADDR 210 r.Add = add 211 return i + int64(r.Siz) 212 } 213 214 /* 215 * divide-and-conquer list-link 216 * sort of LSym* structures. 217 * Used for the data block. 218 */ 219 func datcmp(s1 *LSym, s2 *LSym) int { 220 if s1.Type != s2.Type { 221 return int(s1.Type) - int(s2.Type) 222 } 223 224 // For ppc64, we want to interleave the .got and .toc sections 225 // from input files. Both are type SELFGOT, so in that case 226 // fall through to the name comparison (conveniently, .got 227 // sorts before .toc). 228 if s1.Type != obj.SELFGOT && s1.Size != s2.Size { 229 if s1.Size < s2.Size { 230 return -1 231 } 232 return +1 233 } 234 235 return stringsCompare(s1.Name, s2.Name) 236 } 237 238 func listnextp(s *LSym) **LSym { 239 return &s.Next 240 } 241 242 func listsubp(s *LSym) **LSym { 243 return &s.Sub 244 } 245 246 func listsort(l *LSym, cmp func(*LSym, *LSym) int, nextp func(*LSym) **LSym) *LSym { 247 if l == nil || *nextp(l) == nil { 248 return l 249 } 250 251 l1 := l 252 l2 := l 253 for { 254 l2 = *nextp(l2) 255 if l2 == nil { 256 break 257 } 258 l2 = *nextp(l2) 259 if l2 == nil { 260 break 261 } 262 l1 = *nextp(l1) 263 } 264 265 l2 = *nextp(l1) 266 *nextp(l1) = nil 267 l1 = listsort(l, cmp, nextp) 268 l2 = listsort(l2, cmp, nextp) 269 270 /* set up lead element */ 271 if cmp(l1, l2) < 0 { 272 l = l1 273 l1 = *nextp(l1) 274 } else { 275 l = l2 276 l2 = *nextp(l2) 277 } 278 279 le := l 280 281 for { 282 if l1 == nil { 283 for l2 != nil { 284 *nextp(le) = l2 285 le = l2 286 l2 = *nextp(l2) 287 } 288 289 *nextp(le) = nil 290 break 291 } 292 293 if l2 == nil { 294 for l1 != nil { 295 *nextp(le) = l1 296 le = l1 297 l1 = *nextp(l1) 298 } 299 300 break 301 } 302 303 if cmp(l1, l2) < 0 { 304 *nextp(le) = l1 305 le = l1 306 l1 = *nextp(l1) 307 } else { 308 *nextp(le) = l2 309 le = l2 310 l2 = *nextp(l2) 311 } 312 } 313 314 *nextp(le) = nil 315 return l 316 } 317 318 func relocsym(s *LSym) { 319 var r *Reloc 320 var rs *LSym 321 var i16 int16 322 var off int32 323 var siz int32 324 var fl int32 325 var o int64 326 327 Ctxt.Cursym = s 328 for ri := int32(0); ri < int32(len(s.R)); ri++ { 329 r = &s.R[ri] 330 r.Done = 1 331 off = r.Off 332 siz = int32(r.Siz) 333 if off < 0 || off+siz > int32(len(s.P)) { 334 Diag("%s: invalid relocation %d+%d not in [%d,%d)", s.Name, off, siz, 0, len(s.P)) 335 continue 336 } 337 338 if r.Sym != nil && (r.Sym.Type&(obj.SMASK|obj.SHIDDEN) == 0 || r.Sym.Type&obj.SMASK == obj.SXREF) { 339 // When putting the runtime but not main into a shared library 340 // these symbols are undefined and that's OK. 341 if Buildmode == BuildmodeShared && (r.Sym.Name == "main.main" || r.Sym.Name == "main.init") { 342 r.Sym.Type = obj.SDYNIMPORT 343 } else { 344 Diag("%s: not defined", r.Sym.Name) 345 continue 346 } 347 } 348 349 if r.Type >= 256 { 350 continue 351 } 352 if r.Siz == 0 { // informational relocation - no work to do 353 continue 354 } 355 356 // We need to be able to reference dynimport symbols when linking against 357 // shared libraries, and Solaris needs it always 358 if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() { 359 Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type) 360 } 361 if r.Sym != nil && r.Sym.Type != obj.STLSBSS && !r.Sym.Reachable { 362 Diag("unreachable sym in relocation: %s %s", s.Name, r.Sym.Name) 363 } 364 365 // Android emulates runtime.tlsg as a regular variable. 366 if r.Type == obj.R_TLS && goos == "android" { 367 r.Type = obj.R_ADDR 368 } 369 370 switch r.Type { 371 default: 372 switch siz { 373 default: 374 Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name) 375 case 1: 376 o = int64(s.P[off]) 377 case 2: 378 o = int64(Ctxt.Arch.ByteOrder.Uint16(s.P[off:])) 379 case 4: 380 o = int64(Ctxt.Arch.ByteOrder.Uint32(s.P[off:])) 381 case 8: 382 o = int64(Ctxt.Arch.ByteOrder.Uint64(s.P[off:])) 383 } 384 if Thearch.Archreloc(r, s, &o) < 0 { 385 Diag("unknown reloc %d", r.Type) 386 } 387 388 case obj.R_TLS: 389 if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd { 390 r.Done = 0 391 r.Sym = Ctxt.Tlsg 392 r.Xsym = Ctxt.Tlsg 393 r.Xadd = r.Add 394 o = r.Add 395 break 396 } 397 if Linkmode == LinkInternal && Iself && Thearch.Thechar == '5' { 398 panic("should no longer get here") 399 break 400 } 401 402 r.Done = 0 403 o = 0 404 if Thearch.Thechar != '6' { 405 o = r.Add 406 } 407 408 case obj.R_TLS_LE: 409 if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd { 410 r.Done = 0 411 if r.Sym == nil { 412 r.Sym = Ctxt.Tlsg 413 } 414 r.Xsym = r.Sym 415 r.Xadd = r.Add 416 o = 0 417 if Thearch.Thechar != '6' { 418 o = r.Add 419 } 420 break 421 } 422 423 if Iself && Thearch.Thechar == '5' { 424 // On ELF ARM, the thread pointer is 8 bytes before 425 // the start of the thread-local data block, so add 8 426 // to the actual TLS offset (r->sym->value). 427 // This 8 seems to be a fundamental constant of 428 // ELF on ARM (or maybe Glibc on ARM); it is not 429 // related to the fact that our own TLS storage happens 430 // to take up 8 bytes. 431 o = 8 + r.Sym.Value 432 } else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin { 433 o = int64(Ctxt.Tlsoffset) + r.Add 434 } else if Ctxt.Headtype == obj.Hwindows { 435 o = r.Add 436 } else { 437 log.Fatalf("unexpected R_TLS_LE relocation for %s", Headstr(Ctxt.Headtype)) 438 } 439 440 case obj.R_TLS_IE: 441 if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd { 442 r.Done = 0 443 if r.Sym == nil { 444 r.Sym = Ctxt.Tlsg 445 } 446 r.Xsym = r.Sym 447 r.Xadd = r.Add 448 o = 0 449 if Thearch.Thechar != '6' { 450 o = r.Add 451 } 452 break 453 } 454 log.Fatalf("cannot handle R_TLS_IE when linking internally") 455 456 case obj.R_ADDR: 457 if Linkmode == LinkExternal && r.Sym.Type != obj.SCONST { 458 r.Done = 0 459 460 // set up addend for eventual relocation via outer symbol. 461 rs = r.Sym 462 463 r.Xadd = r.Add 464 for rs.Outer != nil { 465 r.Xadd += Symaddr(rs) - Symaddr(rs.Outer) 466 rs = rs.Outer 467 } 468 469 if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil { 470 Diag("missing section for %s", rs.Name) 471 } 472 r.Xsym = rs 473 474 o = r.Xadd 475 if Iself { 476 if Thearch.Thechar == '6' { 477 o = 0 478 } 479 } else if HEADTYPE == obj.Hdarwin { 480 // ld64 for arm64 has a bug where if the address pointed to by o exists in the 481 // symbol table (dynid >= 0), or is inside a symbol that exists in the symbol 482 // table, then it will add o twice into the relocated value. 483 // The workaround is that on arm64 don't ever add symaddr to o and always use 484 // extern relocation by requiring rs->dynid >= 0. 485 if rs.Type != obj.SHOSTOBJ { 486 if Thearch.Thechar == '7' && rs.Dynid < 0 { 487 Diag("R_ADDR reloc to %s+%d is not supported on darwin/arm64", rs.Name, o) 488 } 489 if Thearch.Thechar != '7' { 490 o += Symaddr(rs) 491 } 492 } 493 } else if HEADTYPE == obj.Hwindows { 494 // nothing to do 495 } else { 496 Diag("unhandled pcrel relocation for %s", headstring) 497 } 498 499 break 500 } 501 502 o = Symaddr(r.Sym) + r.Add 503 504 // On amd64, 4-byte offsets will be sign-extended, so it is impossible to 505 // access more than 2GB of static data; fail at link time is better than 506 // fail at runtime. See https://golang.org/issue/7980. 507 // Instead of special casing only amd64, we treat this as an error on all 508 // 64-bit architectures so as to be future-proof. 509 if int32(o) < 0 && Thearch.Ptrsize > 4 && siz == 4 { 510 Diag("non-pc-relative relocation address is too big: %#x (%#x + %#x)", uint64(o), Symaddr(r.Sym), r.Add) 511 errorexit() 512 } 513 514 // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. 515 case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL: 516 if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) { 517 r.Done = 0 518 519 // set up addend for eventual relocation via outer symbol. 520 rs = r.Sym 521 522 r.Xadd = r.Add 523 for rs.Outer != nil { 524 r.Xadd += Symaddr(rs) - Symaddr(rs.Outer) 525 rs = rs.Outer 526 } 527 528 r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk 529 if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil { 530 Diag("missing section for %s", rs.Name) 531 } 532 r.Xsym = rs 533 534 o = r.Xadd 535 if Iself { 536 if Thearch.Thechar == '6' { 537 o = 0 538 } 539 } else if HEADTYPE == obj.Hdarwin { 540 if r.Type == obj.R_CALL { 541 if rs.Type != obj.SHOSTOBJ { 542 o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr) 543 } 544 o -= int64(r.Off) // relative to section offset, not symbol 545 } else { 546 o += int64(r.Siz) 547 } 548 } else if HEADTYPE == obj.Hwindows && Thearch.Thechar == '6' { // only amd64 needs PCREL 549 // PE/COFF's PC32 relocation uses the address after the relocated 550 // bytes as the base. Compensate by skewing the addend. 551 o += int64(r.Siz) 552 // GNU ld always add VirtualAddress of the .text section to the 553 // relocated address, compensate that. 554 o -= int64(s.Sect.Vaddr - PEBASE) 555 } else { 556 Diag("unhandled pcrel relocation for %s", headstring) 557 } 558 559 break 560 } 561 562 o = 0 563 if r.Sym != nil { 564 o += Symaddr(r.Sym) 565 } 566 567 // NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c 568 // compiler. The expression s->value + r->off + r->siz is int32 + int32 + 569 // uchar, and Plan 9 8c incorrectly treats the expression as type uint32 570 // instead of int32, causing incorrect values when sign extended for adding 571 // to o. The bug only occurs on Plan 9, because this C program is compiled by 572 // the standard host compiler (gcc on most other systems). 573 o += r.Add - (s.Value + int64(r.Off) + int64(int32(r.Siz))) 574 575 case obj.R_SIZE: 576 o = r.Sym.Size + r.Add 577 } 578 579 if r.Variant != RV_NONE { 580 o = Thearch.Archrelocvariant(r, s, o) 581 } 582 583 if false { 584 nam := "<nil>" 585 if r.Sym != nil { 586 nam = r.Sym.Name 587 } 588 fmt.Printf("relocate %s %#x (%#x+%#x, size %d) => %s %#x +%#x [type %d/%d, %x]\n", s.Name, s.Value+int64(off), s.Value, r.Off, r.Siz, nam, Symaddr(r.Sym), r.Add, r.Type, r.Variant, o) 589 } 590 switch siz { 591 default: 592 Ctxt.Cursym = s 593 Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name) 594 fallthrough 595 596 // TODO(rsc): Remove. 597 case 1: 598 s.P[off] = byte(int8(o)) 599 600 case 2: 601 if o != int64(int16(o)) { 602 Diag("relocation address is too big: %#x", o) 603 } 604 i16 = int16(o) 605 Ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16)) 606 607 case 4: 608 if r.Type == obj.R_PCREL || r.Type == obj.R_CALL { 609 if o != int64(int32(o)) { 610 Diag("pc-relative relocation address is too big: %#x", o) 611 } 612 } else { 613 if o != int64(int32(o)) && o != int64(uint32(o)) { 614 Diag("non-pc-relative relocation address is too big: %#x", uint64(o)) 615 } 616 } 617 618 fl = int32(o) 619 Ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl)) 620 621 case 8: 622 Ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o)) 623 } 624 } 625 } 626 627 func reloc() { 628 if Debug['v'] != 0 { 629 fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime()) 630 } 631 Bso.Flush() 632 633 for s := Ctxt.Textp; s != nil; s = s.Next { 634 relocsym(s) 635 } 636 for s := datap; s != nil; s = s.Next { 637 relocsym(s) 638 } 639 } 640 641 func dynrelocsym(s *LSym) { 642 if HEADTYPE == obj.Hwindows && Linkmode != LinkExternal { 643 rel := Linklookup(Ctxt, ".rel", 0) 644 if s == rel { 645 return 646 } 647 var r *Reloc 648 var targ *LSym 649 for ri := 0; ri < len(s.R); ri++ { 650 r = &s.R[ri] 651 targ = r.Sym 652 if targ == nil { 653 continue 654 } 655 if !targ.Reachable { 656 Diag("internal inconsistency: dynamic symbol %s is not reachable.", targ.Name) 657 } 658 if r.Sym.Plt == -2 && r.Sym.Got != -2 { // make dynimport JMP table for PE object files. 659 targ.Plt = int32(rel.Size) 660 r.Sym = rel 661 r.Add = int64(targ.Plt) 662 663 // jmp *addr 664 if Thearch.Thechar == '8' { 665 Adduint8(Ctxt, rel, 0xff) 666 Adduint8(Ctxt, rel, 0x25) 667 Addaddr(Ctxt, rel, targ) 668 Adduint8(Ctxt, rel, 0x90) 669 Adduint8(Ctxt, rel, 0x90) 670 } else { 671 Adduint8(Ctxt, rel, 0xff) 672 Adduint8(Ctxt, rel, 0x24) 673 Adduint8(Ctxt, rel, 0x25) 674 addaddrplus4(Ctxt, rel, targ, 0) 675 Adduint8(Ctxt, rel, 0x90) 676 } 677 } else if r.Sym.Plt >= 0 { 678 r.Sym = rel 679 r.Add = int64(targ.Plt) 680 } 681 } 682 683 return 684 } 685 686 var r *Reloc 687 for ri := 0; ri < len(s.R); ri++ { 688 r = &s.R[ri] 689 if r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT || r.Type >= 256 { 690 if r.Sym != nil && !r.Sym.Reachable { 691 Diag("internal inconsistency: dynamic symbol %s is not reachable.", r.Sym.Name) 692 } 693 Thearch.Adddynrel(s, r) 694 } 695 } 696 } 697 698 func dynreloc() { 699 // -d suppresses dynamic loader format, so we may as well not 700 // compute these sections or mark their symbols as reachable. 701 if Debug['d'] != 0 && HEADTYPE != obj.Hwindows { 702 return 703 } 704 if Debug['v'] != 0 { 705 fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime()) 706 } 707 Bso.Flush() 708 709 for s := Ctxt.Textp; s != nil; s = s.Next { 710 dynrelocsym(s) 711 } 712 for s := datap; s != nil; s = s.Next { 713 dynrelocsym(s) 714 } 715 if Iself { 716 elfdynhash() 717 } 718 } 719 720 func blk(start *LSym, addr int64, size int64) { 721 var sym *LSym 722 723 for sym = start; sym != nil; sym = sym.Next { 724 if sym.Type&obj.SSUB == 0 && sym.Value >= addr { 725 break 726 } 727 } 728 729 eaddr := addr + size 730 var ep []byte 731 var p []byte 732 for ; sym != nil; sym = sym.Next { 733 if sym.Type&obj.SSUB != 0 { 734 continue 735 } 736 if sym.Value >= eaddr { 737 break 738 } 739 Ctxt.Cursym = sym 740 if sym.Value < addr { 741 Diag("phase error: addr=%#x but sym=%#x type=%d", int64(addr), int64(sym.Value), sym.Type) 742 errorexit() 743 } 744 745 for ; addr < sym.Value; addr++ { 746 Cput(0) 747 } 748 p = sym.P 749 ep = p[len(sym.P):] 750 for -cap(p) < -cap(ep) { 751 Cput(uint8(p[0])) 752 p = p[1:] 753 } 754 addr += int64(len(sym.P)) 755 for ; addr < sym.Value+sym.Size; addr++ { 756 Cput(0) 757 } 758 if addr != sym.Value+sym.Size { 759 Diag("phase error: addr=%#x value+size=%#x", int64(addr), int64(sym.Value)+sym.Size) 760 errorexit() 761 } 762 763 if sym.Value+sym.Size >= eaddr { 764 break 765 } 766 } 767 768 for ; addr < eaddr; addr++ { 769 Cput(0) 770 } 771 Cflush() 772 } 773 774 func Codeblk(addr int64, size int64) { 775 if Debug['a'] != 0 { 776 fmt.Fprintf(&Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos()) 777 } 778 779 blk(Ctxt.Textp, addr, size) 780 781 /* again for printing */ 782 if Debug['a'] == 0 { 783 return 784 } 785 786 var sym *LSym 787 for sym = Ctxt.Textp; sym != nil; sym = sym.Next { 788 if !sym.Reachable { 789 continue 790 } 791 if sym.Value >= addr { 792 break 793 } 794 } 795 796 eaddr := addr + size 797 var q []byte 798 for ; sym != nil; sym = sym.Next { 799 if !sym.Reachable { 800 continue 801 } 802 if sym.Value >= eaddr { 803 break 804 } 805 806 if addr < sym.Value { 807 fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr))) 808 for ; addr < sym.Value; addr++ { 809 fmt.Fprintf(&Bso, " %.2x", 0) 810 } 811 fmt.Fprintf(&Bso, "\n") 812 } 813 814 fmt.Fprintf(&Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name) 815 q = sym.P 816 817 for len(q) >= 16 { 818 fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q[:16]) 819 addr += 16 820 q = q[16:] 821 } 822 823 if len(q) > 0 { 824 fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q) 825 addr += int64(len(q)) 826 } 827 } 828 829 if addr < eaddr { 830 fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr))) 831 for ; addr < eaddr; addr++ { 832 fmt.Fprintf(&Bso, " %.2x", 0) 833 } 834 } 835 836 Bso.Flush() 837 } 838 839 func Datblk(addr int64, size int64) { 840 if Debug['a'] != 0 { 841 fmt.Fprintf(&Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos()) 842 } 843 844 blk(datap, addr, size) 845 846 /* again for printing */ 847 if Debug['a'] == 0 { 848 return 849 } 850 851 var sym *LSym 852 for sym = datap; sym != nil; sym = sym.Next { 853 if sym.Value >= addr { 854 break 855 } 856 } 857 858 eaddr := addr + size 859 var ep []byte 860 var i int64 861 var p []byte 862 var r *Reloc 863 var rsname string 864 var typ string 865 for ; sym != nil; sym = sym.Next { 866 if sym.Value >= eaddr { 867 break 868 } 869 if addr < sym.Value { 870 fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint64(addr)) 871 addr = sym.Value 872 } 873 874 fmt.Fprintf(&Bso, "%s\n\t%.8x|", sym.Name, uint(addr)) 875 p = sym.P 876 ep = p[len(sym.P):] 877 for -cap(p) < -cap(ep) { 878 if -cap(p) > -cap(sym.P) && int(-cap(p)+cap(sym.P))%16 == 0 { 879 fmt.Fprintf(&Bso, "\n\t%.8x|", uint(addr+int64(-cap(p)+cap(sym.P)))) 880 } 881 fmt.Fprintf(&Bso, " %.2x", p[0]) 882 p = p[1:] 883 } 884 885 addr += int64(len(sym.P)) 886 for ; addr < sym.Value+sym.Size; addr++ { 887 fmt.Fprintf(&Bso, " %.2x", 0) 888 } 889 fmt.Fprintf(&Bso, "\n") 890 891 if Linkmode == LinkExternal { 892 for i = 0; i < int64(len(sym.R)); i++ { 893 r = &sym.R[i] 894 rsname = "" 895 if r.Sym != nil { 896 rsname = r.Sym.Name 897 } 898 typ = "?" 899 switch r.Type { 900 case obj.R_ADDR: 901 typ = "addr" 902 903 case obj.R_PCREL: 904 typ = "pcrel" 905 906 case obj.R_CALL: 907 typ = "call" 908 } 909 910 fmt.Fprintf(&Bso, "\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, int64(r.Add), int64(r.Sym.Value+r.Add)) 911 } 912 } 913 } 914 915 if addr < eaddr { 916 fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint(addr)) 917 } 918 fmt.Fprintf(&Bso, "\t%.8x|\n", uint(eaddr)) 919 } 920 921 func strnput(s string, n int) { 922 for ; n > 0 && s != ""; s = s[1:] { 923 Cput(uint8(s[0])) 924 n-- 925 } 926 927 for n > 0 { 928 Cput(0) 929 n-- 930 } 931 } 932 933 var strdata []*LSym 934 935 func addstrdata1(arg string) { 936 i := strings.Index(arg, "=") 937 if i < 0 { 938 Exitf("-X flag requires argument of the form importpath.name=value") 939 } 940 addstrdata(arg[:i], arg[i+1:]) 941 } 942 943 func addstrdata(name string, value string) { 944 p := fmt.Sprintf("%s.str", name) 945 sp := Linklookup(Ctxt, p, 0) 946 947 Addstring(sp, value) 948 sp.Type = obj.SRODATA 949 950 s := Linklookup(Ctxt, name, 0) 951 s.Size = 0 952 s.Dupok = 1 953 reachable := s.Reachable 954 Addaddr(Ctxt, s, sp) 955 adduintxx(Ctxt, s, uint64(len(value)), Thearch.Ptrsize) 956 957 // addstring, addaddr, etc., mark the symbols as reachable. 958 // In this case that is not necessarily true, so stick to what 959 // we know before entering this function. 960 s.Reachable = reachable 961 962 strdata = append(strdata, s) 963 964 sp.Reachable = reachable 965 } 966 967 func checkstrdata() { 968 for _, s := range strdata { 969 if s.Type == obj.STEXT { 970 Diag("cannot use -X with text symbol %s", s.Name) 971 } else if s.Gotype != nil && s.Gotype.Name != "type.string" { 972 Diag("cannot use -X with non-string symbol %s", s.Name) 973 } 974 } 975 } 976 977 func Addstring(s *LSym, str string) int64 { 978 if s.Type == 0 { 979 s.Type = obj.SNOPTRDATA 980 } 981 s.Reachable = true 982 r := int32(s.Size) 983 n := len(str) + 1 984 if s.Name == ".shstrtab" { 985 elfsetstring(str, int(r)) 986 } 987 Symgrow(Ctxt, s, int64(r)+int64(n)) 988 copy(s.P[r:], str) 989 s.P[int(r)+len(str)] = 0 990 s.Size += int64(n) 991 return int64(r) 992 } 993 994 // addgostring adds str, as a Go string value, to s. symname is the name of the 995 // symbol used to define the string data and must be unique per linked object. 996 func addgostring(s *LSym, symname, str string) { 997 sym := Linklookup(Ctxt, symname, 0) 998 if sym.Type != obj.Sxxx { 999 Diag("duplicate symname in addgostring: %s", symname) 1000 } 1001 sym.Reachable = true 1002 sym.Local = true 1003 sym.Type = obj.SRODATA 1004 sym.Size = int64(len(str)) 1005 sym.P = []byte(str) 1006 Addaddr(Ctxt, s, sym) 1007 adduint(Ctxt, s, uint64(len(str))) 1008 } 1009 1010 func addinitarrdata(s *LSym) { 1011 p := s.Name + ".ptr" 1012 sp := Linklookup(Ctxt, p, 0) 1013 sp.Type = obj.SINITARR 1014 sp.Size = 0 1015 sp.Dupok = 1 1016 Addaddr(Ctxt, sp, s) 1017 } 1018 1019 func dosymtype() { 1020 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 1021 if len(s.P) > 0 { 1022 if s.Type == obj.SBSS { 1023 s.Type = obj.SDATA 1024 } 1025 if s.Type == obj.SNOPTRBSS { 1026 s.Type = obj.SNOPTRDATA 1027 } 1028 } 1029 // Create a new entry in the .init_array section that points to the 1030 // library initializer function. 1031 switch Buildmode { 1032 case BuildmodeCArchive, BuildmodeCShared: 1033 if s.Name == INITENTRY { 1034 addinitarrdata(s) 1035 } 1036 } 1037 } 1038 } 1039 1040 func symalign(s *LSym) int32 { 1041 if s.Align != 0 { 1042 return s.Align 1043 } 1044 1045 align := int32(Thearch.Maxalign) 1046 for int64(align) > s.Size && align > 1 { 1047 align >>= 1 1048 } 1049 if align < s.Align { 1050 align = s.Align 1051 } 1052 return align 1053 } 1054 1055 func aligndatsize(datsize int64, s *LSym) int64 { 1056 return Rnd(datsize, int64(symalign(s))) 1057 } 1058 1059 // maxalign returns the maximum required alignment for 1060 // the list of symbols s; the list stops when s->type exceeds type. 1061 func maxalign(s *LSym, type_ int) int32 { 1062 var align int32 1063 1064 max := int32(0) 1065 for ; s != nil && int(s.Type) <= type_; s = s.Next { 1066 align = symalign(s) 1067 if max < align { 1068 max = align 1069 } 1070 } 1071 1072 return max 1073 } 1074 1075 const debugGCProg = false 1076 1077 type GCProg struct { 1078 sym *LSym 1079 w gcprog.Writer 1080 } 1081 1082 func (p *GCProg) Init(name string) { 1083 p.sym = Linklookup(Ctxt, name, 0) 1084 p.w.Init(p.writeByte) 1085 if debugGCProg { 1086 fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name) 1087 p.w.Debug(os.Stderr) 1088 } 1089 } 1090 1091 func (p *GCProg) writeByte(x byte) { 1092 Adduint8(Ctxt, p.sym, x) 1093 } 1094 1095 func (p *GCProg) End(size int64) { 1096 p.w.ZeroUntil(size / int64(Thearch.Ptrsize)) 1097 p.w.End() 1098 if debugGCProg { 1099 fmt.Fprintf(os.Stderr, "ld: end GCProg\n") 1100 } 1101 } 1102 1103 func (p *GCProg) AddSym(s *LSym) { 1104 typ := s.Gotype 1105 // Things without pointers should be in SNOPTRDATA or SNOPTRBSS; 1106 // everything we see should have pointers and should therefore have a type. 1107 if typ == nil { 1108 Diag("missing Go type information for global symbol: %s size %d", s.Name, int(s.Size)) 1109 return 1110 } 1111 1112 ptrsize := int64(Thearch.Ptrsize) 1113 nptr := decodetype_ptrdata(typ) / ptrsize 1114 1115 if debugGCProg { 1116 fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr) 1117 } 1118 1119 if decodetype_usegcprog(typ) == 0 { 1120 // Copy pointers from mask into program. 1121 mask := decodetype_gcmask(typ) 1122 for i := int64(0); i < nptr; i++ { 1123 if (mask[i/8]>>uint(i%8))&1 != 0 { 1124 p.w.Ptr(s.Value/ptrsize + i) 1125 } 1126 } 1127 return 1128 } 1129 1130 // Copy program. 1131 prog := decodetype_gcprog(typ) 1132 p.w.ZeroUntil(s.Value / ptrsize) 1133 p.w.Append(prog[4:], nptr) 1134 } 1135 1136 func growdatsize(datsizep *int64, s *LSym) { 1137 datsize := *datsizep 1138 const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31) 1139 switch { 1140 case s.Size < 0: 1141 Diag("%s: negative size (%d bytes)", s.Name, s.Size) 1142 case s.Size > cutoff: 1143 Diag("%s: symbol too large (%d bytes)", s.Name, s.Size) 1144 case datsize <= cutoff && datsize+s.Size > cutoff: 1145 Diag("%s: too much data (over %d bytes)", s.Name, cutoff) 1146 } 1147 *datsizep = datsize + s.Size 1148 } 1149 1150 func dodata() { 1151 if Debug['v'] != 0 { 1152 fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime()) 1153 } 1154 Bso.Flush() 1155 1156 var last *LSym 1157 datap = nil 1158 1159 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 1160 if !s.Reachable || s.Special != 0 { 1161 continue 1162 } 1163 if obj.STEXT < s.Type && s.Type < obj.SXREF { 1164 if s.Onlist != 0 { 1165 log.Fatalf("symbol %s listed multiple times", s.Name) 1166 } 1167 s.Onlist = 1 1168 if last == nil { 1169 datap = s 1170 } else { 1171 last.Next = s 1172 } 1173 s.Next = nil 1174 last = s 1175 } 1176 } 1177 1178 for s := datap; s != nil; s = s.Next { 1179 if int64(len(s.P)) > s.Size { 1180 Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P)) 1181 } 1182 } 1183 1184 /* 1185 * now that we have the datap list, but before we start 1186 * to assign addresses, record all the necessary 1187 * dynamic relocations. these will grow the relocation 1188 * symbol, which is itself data. 1189 * 1190 * on darwin, we need the symbol table numbers for dynreloc. 1191 */ 1192 if HEADTYPE == obj.Hdarwin { 1193 machosymorder() 1194 } 1195 dynreloc() 1196 1197 /* some symbols may no longer belong in datap (Mach-O) */ 1198 var l **LSym 1199 var s *LSym 1200 for l = &datap; ; { 1201 s = *l 1202 if s == nil { 1203 break 1204 } 1205 1206 if s.Type <= obj.STEXT || obj.SXREF <= s.Type { 1207 *l = s.Next 1208 } else { 1209 l = &s.Next 1210 } 1211 } 1212 1213 *l = nil 1214 1215 if UseRelro() { 1216 // "read only" data with relocations needs to go in its own section 1217 // when building a shared library. We do this by boosting objects of 1218 // type SXXX with relocations to type SXXXRELRO. 1219 for s := datap; s != nil; s = s.Next { 1220 if (s.Type >= obj.STYPE && s.Type <= obj.SFUNCTAB && len(s.R) > 0) || s.Type == obj.SGOSTRING { 1221 s.Type += (obj.STYPERELRO - obj.STYPE) 1222 if s.Outer != nil { 1223 s.Outer.Type = s.Type 1224 } 1225 } 1226 } 1227 // Check that we haven't made two symbols with the same .Outer into 1228 // different types (because references two symbols with non-nil Outer 1229 // become references to the outer symbol + offset it's vital that the 1230 // symbol and the outer end up in the same section). 1231 for s := datap; s != nil; s = s.Next { 1232 if s.Outer != nil && s.Outer.Type != s.Type { 1233 Diag("inconsistent types for %s and its Outer %s (%d != %d)", 1234 s.Name, s.Outer.Name, s.Type, s.Outer.Type) 1235 } 1236 } 1237 1238 } 1239 1240 datap = listsort(datap, datcmp, listnextp) 1241 1242 if Iself { 1243 // Make .rela and .rela.plt contiguous, the ELF ABI requires this 1244 // and Solaris actually cares. 1245 var relplt *LSym 1246 for l = &datap; *l != nil; l = &(*l).Next { 1247 if (*l).Name == ".rel.plt" || (*l).Name == ".rela.plt" { 1248 relplt = (*l) 1249 *l = (*l).Next 1250 break 1251 } 1252 } 1253 if relplt != nil { 1254 for s = datap; s != nil; s = s.Next { 1255 if s.Name == ".rel" || s.Name == ".rela" { 1256 relplt.Next = s.Next 1257 s.Next = relplt 1258 } 1259 } 1260 } 1261 } 1262 1263 /* 1264 * allocate sections. list is sorted by type, 1265 * so we can just walk it for each piece we want to emit. 1266 * segdata is processed before segtext, because we need 1267 * to see all symbols in the .data and .bss sections in order 1268 * to generate garbage collection information. 1269 */ 1270 1271 /* begin segdata */ 1272 1273 /* skip symbols belonging to segtext */ 1274 s = datap 1275 1276 for ; s != nil && s.Type < obj.SELFSECT; s = s.Next { 1277 } 1278 1279 /* writable ELF sections */ 1280 datsize := int64(0) 1281 1282 var sect *Section 1283 for ; s != nil && s.Type < obj.SELFGOT; s = s.Next { 1284 sect = addsection(&Segdata, s.Name, 06) 1285 sect.Align = symalign(s) 1286 datsize = Rnd(datsize, int64(sect.Align)) 1287 sect.Vaddr = uint64(datsize) 1288 s.Sect = sect 1289 s.Type = obj.SDATA 1290 s.Value = int64(uint64(datsize) - sect.Vaddr) 1291 growdatsize(&datsize, s) 1292 sect.Length = uint64(datsize) - sect.Vaddr 1293 } 1294 1295 /* .got (and .toc on ppc64) */ 1296 if s.Type == obj.SELFGOT { 1297 sect := addsection(&Segdata, ".got", 06) 1298 sect.Align = maxalign(s, obj.SELFGOT) 1299 datsize = Rnd(datsize, int64(sect.Align)) 1300 sect.Vaddr = uint64(datsize) 1301 var toc *LSym 1302 for ; s != nil && s.Type == obj.SELFGOT; s = s.Next { 1303 datsize = aligndatsize(datsize, s) 1304 s.Sect = sect 1305 s.Type = obj.SDATA 1306 s.Value = int64(uint64(datsize) - sect.Vaddr) 1307 1308 // Resolve .TOC. symbol for this object file (ppc64) 1309 toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version)) 1310 1311 if toc != nil { 1312 toc.Sect = sect 1313 toc.Outer = s 1314 toc.Sub = s.Sub 1315 s.Sub = toc 1316 1317 toc.Value = 0x8000 1318 } 1319 1320 growdatsize(&datsize, s) 1321 } 1322 1323 sect.Length = uint64(datsize) - sect.Vaddr 1324 } 1325 1326 /* pointer-free data */ 1327 sect = addsection(&Segdata, ".noptrdata", 06) 1328 1329 sect.Align = maxalign(s, obj.SINITARR-1) 1330 datsize = Rnd(datsize, int64(sect.Align)) 1331 sect.Vaddr = uint64(datsize) 1332 Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect 1333 Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect 1334 for ; s != nil && s.Type < obj.SINITARR; s = s.Next { 1335 datsize = aligndatsize(datsize, s) 1336 s.Sect = sect 1337 s.Type = obj.SDATA 1338 s.Value = int64(uint64(datsize) - sect.Vaddr) 1339 growdatsize(&datsize, s) 1340 } 1341 1342 sect.Length = uint64(datsize) - sect.Vaddr 1343 1344 hasinitarr := Linkshared 1345 1346 /* shared library initializer */ 1347 switch Buildmode { 1348 case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared: 1349 hasinitarr = true 1350 } 1351 1352 if hasinitarr { 1353 sect := addsection(&Segdata, ".init_array", 06) 1354 sect.Align = maxalign(s, obj.SINITARR) 1355 datsize = Rnd(datsize, int64(sect.Align)) 1356 sect.Vaddr = uint64(datsize) 1357 for ; s != nil && s.Type == obj.SINITARR; s = s.Next { 1358 datsize = aligndatsize(datsize, s) 1359 s.Sect = sect 1360 s.Value = int64(uint64(datsize) - sect.Vaddr) 1361 growdatsize(&datsize, s) 1362 } 1363 1364 sect.Length = uint64(datsize) - sect.Vaddr 1365 } 1366 1367 /* data */ 1368 sect = addsection(&Segdata, ".data", 06) 1369 sect.Align = maxalign(s, obj.SBSS-1) 1370 datsize = Rnd(datsize, int64(sect.Align)) 1371 sect.Vaddr = uint64(datsize) 1372 Linklookup(Ctxt, "runtime.data", 0).Sect = sect 1373 Linklookup(Ctxt, "runtime.edata", 0).Sect = sect 1374 var gc GCProg 1375 gc.Init("runtime.gcdata") 1376 for ; s != nil && s.Type < obj.SBSS; s = s.Next { 1377 if s.Type == obj.SINITARR { 1378 Ctxt.Cursym = s 1379 Diag("unexpected symbol type %d", s.Type) 1380 } 1381 1382 s.Sect = sect 1383 s.Type = obj.SDATA 1384 datsize = aligndatsize(datsize, s) 1385 s.Value = int64(uint64(datsize) - sect.Vaddr) 1386 gc.AddSym(s) 1387 growdatsize(&datsize, s) 1388 } 1389 sect.Length = uint64(datsize) - sect.Vaddr 1390 gc.End(int64(sect.Length)) 1391 1392 /* bss */ 1393 sect = addsection(&Segdata, ".bss", 06) 1394 sect.Align = maxalign(s, obj.SNOPTRBSS-1) 1395 datsize = Rnd(datsize, int64(sect.Align)) 1396 sect.Vaddr = uint64(datsize) 1397 Linklookup(Ctxt, "runtime.bss", 0).Sect = sect 1398 Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect 1399 gc = GCProg{} 1400 gc.Init("runtime.gcbss") 1401 for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next { 1402 s.Sect = sect 1403 datsize = aligndatsize(datsize, s) 1404 s.Value = int64(uint64(datsize) - sect.Vaddr) 1405 gc.AddSym(s) 1406 growdatsize(&datsize, s) 1407 } 1408 sect.Length = uint64(datsize) - sect.Vaddr 1409 gc.End(int64(sect.Length)) 1410 1411 /* pointer-free bss */ 1412 sect = addsection(&Segdata, ".noptrbss", 06) 1413 1414 sect.Align = maxalign(s, obj.SNOPTRBSS) 1415 datsize = Rnd(datsize, int64(sect.Align)) 1416 sect.Vaddr = uint64(datsize) 1417 Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect 1418 Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect 1419 for ; s != nil && s.Type == obj.SNOPTRBSS; s = s.Next { 1420 datsize = aligndatsize(datsize, s) 1421 s.Sect = sect 1422 s.Value = int64(uint64(datsize) - sect.Vaddr) 1423 growdatsize(&datsize, s) 1424 } 1425 1426 sect.Length = uint64(datsize) - sect.Vaddr 1427 Linklookup(Ctxt, "runtime.end", 0).Sect = sect 1428 1429 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1430 if datsize != int64(uint32(datsize)) { 1431 Diag("data or bss segment too large") 1432 } 1433 1434 if s != nil && s.Type == obj.STLSBSS { 1435 if Iself && (Linkmode == LinkExternal || Debug['d'] == 0) && HEADTYPE != obj.Hopenbsd { 1436 sect = addsection(&Segdata, ".tbss", 06) 1437 sect.Align = int32(Thearch.Ptrsize) 1438 sect.Vaddr = 0 1439 } else { 1440 sect = nil 1441 } 1442 datsize = 0 1443 1444 for ; s != nil && s.Type == obj.STLSBSS; s = s.Next { 1445 datsize = aligndatsize(datsize, s) 1446 s.Sect = sect 1447 s.Value = datsize 1448 growdatsize(&datsize, s) 1449 } 1450 1451 if sect != nil { 1452 sect.Length = uint64(datsize) 1453 } 1454 } 1455 1456 if s != nil { 1457 Ctxt.Cursym = nil 1458 Diag("unexpected symbol type %d for %s", s.Type, s.Name) 1459 } 1460 1461 /* 1462 * We finished data, begin read-only data. 1463 * Not all systems support a separate read-only non-executable data section. 1464 * ELF systems do. 1465 * OS X and Plan 9 do not. 1466 * Windows PE may, but if so we have not implemented it. 1467 * And if we're using external linking mode, the point is moot, 1468 * since it's not our decision; that code expects the sections in 1469 * segtext. 1470 */ 1471 var segro *Segment 1472 if Iself && Linkmode == LinkInternal { 1473 segro = &Segrodata 1474 } else { 1475 segro = &Segtext 1476 } 1477 1478 s = datap 1479 1480 datsize = 0 1481 1482 /* read-only executable ELF, Mach-O sections */ 1483 for ; s != nil && s.Type < obj.STYPE; s = s.Next { 1484 sect = addsection(&Segtext, s.Name, 04) 1485 sect.Align = symalign(s) 1486 datsize = Rnd(datsize, int64(sect.Align)) 1487 sect.Vaddr = uint64(datsize) 1488 s.Sect = sect 1489 s.Type = obj.SRODATA 1490 s.Value = int64(uint64(datsize) - sect.Vaddr) 1491 growdatsize(&datsize, s) 1492 sect.Length = uint64(datsize) - sect.Vaddr 1493 } 1494 1495 /* read-only data */ 1496 sect = addsection(segro, ".rodata", 04) 1497 1498 sect.Align = maxalign(s, obj.STYPERELRO-1) 1499 datsize = Rnd(datsize, int64(sect.Align)) 1500 sect.Vaddr = 0 1501 Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect 1502 Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect 1503 for ; s != nil && s.Type < obj.STYPERELRO; s = s.Next { 1504 datsize = aligndatsize(datsize, s) 1505 s.Sect = sect 1506 s.Type = obj.SRODATA 1507 s.Value = int64(uint64(datsize) - sect.Vaddr) 1508 growdatsize(&datsize, s) 1509 } 1510 1511 sect.Length = uint64(datsize) - sect.Vaddr 1512 1513 // There is some data that are conceptually read-only but are written to by 1514 // relocations. On GNU systems, we can arrange for the dynamic linker to 1515 // mprotect sections after relocations are applied by giving them write 1516 // permissions in the object file and calling them ".data.rel.ro.FOO". We 1517 // divide the .rodata section between actual .rodata and .data.rel.ro.rodata, 1518 // but for the other sections that this applies to, we just write a read-only 1519 // .FOO section or a read-write .data.rel.ro.FOO section depending on the 1520 // situation. 1521 // TODO(mwhudson): It would make sense to do this more widely, but it makes 1522 // the system linker segfault on darwin. 1523 relro_perms := 04 1524 relro_prefix := "" 1525 1526 if UseRelro() { 1527 relro_perms = 06 1528 relro_prefix = ".data.rel.ro" 1529 /* data only written by relocations */ 1530 sect = addsection(segro, ".data.rel.ro", 06) 1531 1532 sect.Align = maxalign(s, obj.STYPELINK-1) 1533 datsize = Rnd(datsize, int64(sect.Align)) 1534 sect.Vaddr = 0 1535 for ; s != nil && s.Type < obj.STYPELINK; s = s.Next { 1536 datsize = aligndatsize(datsize, s) 1537 if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect { 1538 Diag("s.Outer (%s) in different section from s (%s)", s.Outer.Name, s.Name) 1539 } 1540 s.Sect = sect 1541 s.Type = obj.SRODATA 1542 s.Value = int64(uint64(datsize) - sect.Vaddr) 1543 growdatsize(&datsize, s) 1544 } 1545 1546 sect.Length = uint64(datsize) - sect.Vaddr 1547 1548 } 1549 1550 /* typelink */ 1551 sect = addsection(segro, relro_prefix+".typelink", relro_perms) 1552 1553 sect.Align = maxalign(s, obj.STYPELINK) 1554 datsize = Rnd(datsize, int64(sect.Align)) 1555 sect.Vaddr = uint64(datsize) 1556 Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect 1557 Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect 1558 for ; s != nil && s.Type == obj.STYPELINK; s = s.Next { 1559 datsize = aligndatsize(datsize, s) 1560 s.Sect = sect 1561 s.Type = obj.SRODATA 1562 s.Value = int64(uint64(datsize) - sect.Vaddr) 1563 growdatsize(&datsize, s) 1564 } 1565 1566 sect.Length = uint64(datsize) - sect.Vaddr 1567 1568 /* gosymtab */ 1569 sect = addsection(segro, relro_prefix+".gosymtab", relro_perms) 1570 1571 sect.Align = maxalign(s, obj.SPCLNTAB-1) 1572 datsize = Rnd(datsize, int64(sect.Align)) 1573 sect.Vaddr = uint64(datsize) 1574 Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect 1575 Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect 1576 for ; s != nil && s.Type < obj.SPCLNTAB; s = s.Next { 1577 datsize = aligndatsize(datsize, s) 1578 s.Sect = sect 1579 s.Type = obj.SRODATA 1580 s.Value = int64(uint64(datsize) - sect.Vaddr) 1581 growdatsize(&datsize, s) 1582 } 1583 1584 sect.Length = uint64(datsize) - sect.Vaddr 1585 1586 /* gopclntab */ 1587 sect = addsection(segro, relro_prefix+".gopclntab", relro_perms) 1588 1589 sect.Align = maxalign(s, obj.SELFROSECT-1) 1590 datsize = Rnd(datsize, int64(sect.Align)) 1591 sect.Vaddr = uint64(datsize) 1592 Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect 1593 Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect 1594 for ; s != nil && s.Type < obj.SELFROSECT; s = s.Next { 1595 datsize = aligndatsize(datsize, s) 1596 s.Sect = sect 1597 s.Type = obj.SRODATA 1598 s.Value = int64(uint64(datsize) - sect.Vaddr) 1599 growdatsize(&datsize, s) 1600 } 1601 1602 sect.Length = uint64(datsize) - sect.Vaddr 1603 1604 /* read-only ELF, Mach-O sections */ 1605 for ; s != nil && s.Type < obj.SELFSECT; s = s.Next { 1606 sect = addsection(segro, s.Name, 04) 1607 sect.Align = symalign(s) 1608 datsize = Rnd(datsize, int64(sect.Align)) 1609 sect.Vaddr = uint64(datsize) 1610 s.Sect = sect 1611 s.Type = obj.SRODATA 1612 s.Value = int64(uint64(datsize) - sect.Vaddr) 1613 growdatsize(&datsize, s) 1614 sect.Length = uint64(datsize) - sect.Vaddr 1615 } 1616 1617 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1618 if datsize != int64(uint32(datsize)) { 1619 Diag("read-only data segment too large") 1620 } 1621 1622 /* number the sections */ 1623 n := int32(1) 1624 1625 for sect := Segtext.Sect; sect != nil; sect = sect.Next { 1626 sect.Extnum = int16(n) 1627 n++ 1628 } 1629 for sect := Segrodata.Sect; sect != nil; sect = sect.Next { 1630 sect.Extnum = int16(n) 1631 n++ 1632 } 1633 for sect := Segdata.Sect; sect != nil; sect = sect.Next { 1634 sect.Extnum = int16(n) 1635 n++ 1636 } 1637 } 1638 1639 // Add buildid to beginning of text segment, on non-ELF systems. 1640 // Non-ELF binary formats are not always flexible enough to 1641 // give us a place to put the Go build ID. On those systems, we put it 1642 // at the very beginning of the text segment. 1643 // This ``header'' is read by cmd/go. 1644 func textbuildid() { 1645 if Iself || buildid == "" { 1646 return 1647 } 1648 1649 sym := Linklookup(Ctxt, "go.buildid", 0) 1650 sym.Reachable = true 1651 // The \xff is invalid UTF-8, meant to make it less likely 1652 // to find one of these accidentally. 1653 data := "\xff Go build ID: " + strconv.Quote(buildid) + "\n \xff" 1654 sym.Type = obj.STEXT 1655 sym.P = []byte(data) 1656 sym.Size = int64(len(sym.P)) 1657 1658 sym.Next = Ctxt.Textp 1659 Ctxt.Textp = sym 1660 } 1661 1662 // assign addresses to text 1663 func textaddress() { 1664 var sub *LSym 1665 1666 addsection(&Segtext, ".text", 05) 1667 1668 // Assign PCs in text segment. 1669 // Could parallelize, by assigning to text 1670 // and then letting threads copy down, but probably not worth it. 1671 sect := Segtext.Sect 1672 1673 sect.Align = int32(Funcalign) 1674 Linklookup(Ctxt, "runtime.text", 0).Sect = sect 1675 Linklookup(Ctxt, "runtime.etext", 0).Sect = sect 1676 va := uint64(INITTEXT) 1677 sect.Vaddr = va 1678 for sym := Ctxt.Textp; sym != nil; sym = sym.Next { 1679 sym.Sect = sect 1680 if sym.Type&obj.SSUB != 0 { 1681 continue 1682 } 1683 if sym.Align != 0 { 1684 va = uint64(Rnd(int64(va), int64(sym.Align))) 1685 } else { 1686 va = uint64(Rnd(int64(va), int64(Funcalign))) 1687 } 1688 sym.Value = 0 1689 for sub = sym; sub != nil; sub = sub.Sub { 1690 sub.Value += int64(va) 1691 } 1692 if sym.Size == 0 && sym.Sub != nil { 1693 Ctxt.Cursym = sym 1694 } 1695 if sym.Size < MINFUNC { 1696 va += MINFUNC // spacing required for findfunctab 1697 } else { 1698 va += uint64(sym.Size) 1699 } 1700 } 1701 1702 sect.Length = va - sect.Vaddr 1703 } 1704 1705 // assign addresses 1706 func address() { 1707 va := uint64(INITTEXT) 1708 Segtext.Rwx = 05 1709 Segtext.Vaddr = va 1710 Segtext.Fileoff = uint64(HEADR) 1711 for s := Segtext.Sect; s != nil; s = s.Next { 1712 va = uint64(Rnd(int64(va), int64(s.Align))) 1713 s.Vaddr = va 1714 va += s.Length 1715 } 1716 1717 Segtext.Length = va - uint64(INITTEXT) 1718 Segtext.Filelen = Segtext.Length 1719 if HEADTYPE == obj.Hnacl { 1720 va += 32 // room for the "halt sled" 1721 } 1722 1723 if Segrodata.Sect != nil { 1724 // align to page boundary so as not to mix 1725 // rodata and executable text. 1726 va = uint64(Rnd(int64(va), int64(INITRND))) 1727 1728 Segrodata.Rwx = 04 1729 Segrodata.Vaddr = va 1730 Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff 1731 Segrodata.Filelen = 0 1732 for s := Segrodata.Sect; s != nil; s = s.Next { 1733 va = uint64(Rnd(int64(va), int64(s.Align))) 1734 s.Vaddr = va 1735 va += s.Length 1736 } 1737 1738 Segrodata.Length = va - Segrodata.Vaddr 1739 Segrodata.Filelen = Segrodata.Length 1740 } 1741 1742 va = uint64(Rnd(int64(va), int64(INITRND))) 1743 Segdata.Rwx = 06 1744 Segdata.Vaddr = va 1745 Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff 1746 Segdata.Filelen = 0 1747 if HEADTYPE == obj.Hwindows { 1748 Segdata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN)) 1749 } 1750 if HEADTYPE == obj.Hplan9 { 1751 Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen 1752 } 1753 var data *Section 1754 var noptr *Section 1755 var bss *Section 1756 var noptrbss *Section 1757 var vlen int64 1758 for s := Segdata.Sect; s != nil; s = s.Next { 1759 if Iself && s.Name == ".tbss" { 1760 continue 1761 } 1762 vlen = int64(s.Length) 1763 if s.Next != nil && !(Iself && s.Next.Name == ".tbss") { 1764 vlen = int64(s.Next.Vaddr - s.Vaddr) 1765 } 1766 s.Vaddr = va 1767 va += uint64(vlen) 1768 Segdata.Length = va - Segdata.Vaddr 1769 if s.Name == ".data" { 1770 data = s 1771 } 1772 if s.Name == ".noptrdata" { 1773 noptr = s 1774 } 1775 if s.Name == ".bss" { 1776 bss = s 1777 } 1778 if s.Name == ".noptrbss" { 1779 noptrbss = s 1780 } 1781 } 1782 1783 Segdata.Filelen = bss.Vaddr - Segdata.Vaddr 1784 1785 text := Segtext.Sect 1786 var rodata *Section 1787 if Segrodata.Sect != nil { 1788 rodata = Segrodata.Sect 1789 } else { 1790 rodata = text.Next 1791 } 1792 typelink := rodata.Next 1793 if UseRelro() { 1794 // There is another section (.data.rel.ro) when building a shared 1795 // object on elf systems. 1796 typelink = typelink.Next 1797 } 1798 symtab := typelink.Next 1799 pclntab := symtab.Next 1800 1801 var sub *LSym 1802 for sym := datap; sym != nil; sym = sym.Next { 1803 Ctxt.Cursym = sym 1804 if sym.Sect != nil { 1805 sym.Value += int64(sym.Sect.Vaddr) 1806 } 1807 for sub = sym.Sub; sub != nil; sub = sub.Sub { 1808 sub.Value += sym.Value 1809 } 1810 } 1811 1812 if Buildmode == BuildmodeShared { 1813 s := Linklookup(Ctxt, "go.link.abihashbytes", 0) 1814 sectSym := Linklookup(Ctxt, ".note.go.abihash", 0) 1815 s.Sect = sectSym.Sect 1816 s.Value = int64(sectSym.Sect.Vaddr + 16) 1817 } 1818 1819 xdefine("runtime.text", obj.STEXT, int64(text.Vaddr)) 1820 xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length)) 1821 xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr)) 1822 xdefine("runtime.erodata", obj.SRODATA, int64(rodata.Vaddr+rodata.Length)) 1823 xdefine("runtime.typelink", obj.SRODATA, int64(typelink.Vaddr)) 1824 xdefine("runtime.etypelink", obj.SRODATA, int64(typelink.Vaddr+typelink.Length)) 1825 1826 sym := Linklookup(Ctxt, "runtime.gcdata", 0) 1827 sym.Local = true 1828 xdefine("runtime.egcdata", obj.SRODATA, Symaddr(sym)+sym.Size) 1829 Linklookup(Ctxt, "runtime.egcdata", 0).Sect = sym.Sect 1830 1831 sym = Linklookup(Ctxt, "runtime.gcbss", 0) 1832 sym.Local = true 1833 xdefine("runtime.egcbss", obj.SRODATA, Symaddr(sym)+sym.Size) 1834 Linklookup(Ctxt, "runtime.egcbss", 0).Sect = sym.Sect 1835 1836 xdefine("runtime.symtab", obj.SRODATA, int64(symtab.Vaddr)) 1837 xdefine("runtime.esymtab", obj.SRODATA, int64(symtab.Vaddr+symtab.Length)) 1838 xdefine("runtime.pclntab", obj.SRODATA, int64(pclntab.Vaddr)) 1839 xdefine("runtime.epclntab", obj.SRODATA, int64(pclntab.Vaddr+pclntab.Length)) 1840 xdefine("runtime.noptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr)) 1841 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length)) 1842 xdefine("runtime.bss", obj.SBSS, int64(bss.Vaddr)) 1843 xdefine("runtime.ebss", obj.SBSS, int64(bss.Vaddr+bss.Length)) 1844 xdefine("runtime.data", obj.SDATA, int64(data.Vaddr)) 1845 xdefine("runtime.edata", obj.SDATA, int64(data.Vaddr+data.Length)) 1846 xdefine("runtime.noptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr)) 1847 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length)) 1848 xdefine("runtime.end", obj.SBSS, int64(Segdata.Vaddr+Segdata.Length)) 1849 }