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