github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/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 o = 0 373 if Thearch.Archreloc(r, s, &o) < 0 { 374 Diag("unknown reloc %d", r.Type) 375 } 376 377 case obj.R_TLS: 378 if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd { 379 r.Done = 0 380 r.Sym = Ctxt.Tlsg 381 r.Xsym = Ctxt.Tlsg 382 r.Xadd = r.Add 383 o = r.Add 384 break 385 } 386 if Linkmode == LinkInternal && Iself && Thearch.Thechar == '5' { 387 // On ELF ARM, the thread pointer is 8 bytes before 388 // the start of the thread-local data block, so add 8 389 // to the actual TLS offset (r->sym->value). 390 // This 8 seems to be a fundamental constant of 391 // ELF on ARM (or maybe Glibc on ARM); it is not 392 // related to the fact that our own TLS storage happens 393 // to take up 8 bytes. 394 o = 8 + r.Sym.Value 395 396 break 397 } 398 399 r.Done = 0 400 o = 0 401 if Thearch.Thechar != '6' { 402 o = r.Add 403 } 404 405 case obj.R_TLS_LE: 406 if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd { 407 r.Done = 0 408 r.Sym = Ctxt.Tlsg 409 r.Xsym = Ctxt.Tlsg 410 r.Xadd = r.Add 411 o = 0 412 if Thearch.Thechar != '6' { 413 o = r.Add 414 } 415 break 416 } 417 418 if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin { 419 o = int64(Ctxt.Tlsoffset) + r.Add 420 } else if Ctxt.Headtype == obj.Hwindows { 421 o = r.Add 422 } else { 423 log.Fatalf("unexpected R_TLS_LE relocation for %s", Headstr(Ctxt.Headtype)) 424 } 425 426 case obj.R_TLS_IE: 427 if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd { 428 r.Done = 0 429 r.Sym = Ctxt.Tlsg 430 r.Xsym = Ctxt.Tlsg 431 r.Xadd = r.Add 432 o = 0 433 if Thearch.Thechar != '6' { 434 o = r.Add 435 } 436 break 437 } 438 log.Fatalf("cannot handle R_TLS_IE when linking internally") 439 440 case obj.R_ADDR: 441 if Linkmode == LinkExternal && r.Sym.Type != obj.SCONST { 442 r.Done = 0 443 444 // set up addend for eventual relocation via outer symbol. 445 rs = r.Sym 446 447 r.Xadd = r.Add 448 for rs.Outer != nil { 449 r.Xadd += Symaddr(rs) - Symaddr(rs.Outer) 450 rs = rs.Outer 451 } 452 453 if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil { 454 Diag("missing section for %s", rs.Name) 455 } 456 r.Xsym = rs 457 458 o = r.Xadd 459 if Iself { 460 if Thearch.Thechar == '6' { 461 o = 0 462 } 463 } else if HEADTYPE == obj.Hdarwin { 464 // ld64 for arm64 has a bug where if the address pointed to by o exists in the 465 // symbol table (dynid >= 0), or is inside a symbol that exists in the symbol 466 // table, then it will add o twice into the relocated value. 467 // The workaround is that on arm64 don't ever add symaddr to o and always use 468 // extern relocation by requiring rs->dynid >= 0. 469 if rs.Type != obj.SHOSTOBJ { 470 if Thearch.Thechar == '7' && rs.Dynid < 0 { 471 Diag("R_ADDR reloc to %s+%d is not supported on darwin/arm64", rs.Name, o) 472 } 473 if Thearch.Thechar != '7' { 474 o += Symaddr(rs) 475 } 476 } 477 } else if HEADTYPE == obj.Hwindows { 478 // nothing to do 479 } else { 480 Diag("unhandled pcrel relocation for %s", headstring) 481 } 482 483 break 484 } 485 486 o = Symaddr(r.Sym) + r.Add 487 488 // On amd64, 4-byte offsets will be sign-extended, so it is impossible to 489 // access more than 2GB of static data; fail at link time is better than 490 // fail at runtime. See https://golang.org/issue/7980. 491 // Instead of special casing only amd64, we treat this as an error on all 492 // 64-bit architectures so as to be future-proof. 493 if int32(o) < 0 && Thearch.Ptrsize > 4 && siz == 4 { 494 Diag("non-pc-relative relocation address is too big: %#x (%#x + %#x)", uint64(o), Symaddr(r.Sym), r.Add) 495 errorexit() 496 } 497 498 // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. 499 case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL: 500 if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) { 501 r.Done = 0 502 503 // set up addend for eventual relocation via outer symbol. 504 rs = r.Sym 505 506 r.Xadd = r.Add 507 for rs.Outer != nil { 508 r.Xadd += Symaddr(rs) - Symaddr(rs.Outer) 509 rs = rs.Outer 510 } 511 512 r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk 513 if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil { 514 Diag("missing section for %s", rs.Name) 515 } 516 r.Xsym = rs 517 518 o = r.Xadd 519 if Iself { 520 if Thearch.Thechar == '6' { 521 o = 0 522 } 523 } else if HEADTYPE == obj.Hdarwin { 524 if r.Type == obj.R_CALL { 525 if rs.Type != obj.SHOSTOBJ { 526 o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr) 527 } 528 o -= int64(r.Off) // relative to section offset, not symbol 529 } else { 530 o += int64(r.Siz) 531 } 532 } else if HEADTYPE == obj.Hwindows && Thearch.Thechar == '6' { // only amd64 needs PCREL 533 // PE/COFF's PC32 relocation uses the address after the relocated 534 // bytes as the base. Compensate by skewing the addend. 535 o += int64(r.Siz) 536 // GNU ld always add VirtualAddress of the .text section to the 537 // relocated address, compensate that. 538 o -= int64(s.Sect.Vaddr - PEBASE) 539 } else { 540 Diag("unhandled pcrel relocation for %s", headstring) 541 } 542 543 break 544 } 545 546 o = 0 547 if r.Sym != nil { 548 o += Symaddr(r.Sym) 549 } 550 551 // NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c 552 // compiler. The expression s->value + r->off + r->siz is int32 + int32 + 553 // uchar, and Plan 9 8c incorrectly treats the expression as type uint32 554 // instead of int32, causing incorrect values when sign extended for adding 555 // to o. The bug only occurs on Plan 9, because this C program is compiled by 556 // the standard host compiler (gcc on most other systems). 557 o += r.Add - (s.Value + int64(r.Off) + int64(int32(r.Siz))) 558 559 case obj.R_SIZE: 560 o = r.Sym.Size + r.Add 561 } 562 563 if r.Variant != RV_NONE { 564 o = Thearch.Archrelocvariant(r, s, o) 565 } 566 567 if false { 568 nam := "<nil>" 569 if r.Sym != nil { 570 nam = r.Sym.Name 571 } 572 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) 573 } 574 switch siz { 575 default: 576 Ctxt.Cursym = s 577 Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name) 578 fallthrough 579 580 // TODO(rsc): Remove. 581 case 1: 582 s.P[off] = byte(int8(o)) 583 584 case 2: 585 if o != int64(int16(o)) { 586 Diag("relocation address is too big: %#x", o) 587 } 588 i16 = int16(o) 589 Ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16)) 590 591 case 4: 592 if r.Type == obj.R_PCREL || r.Type == obj.R_CALL { 593 if o != int64(int32(o)) { 594 Diag("pc-relative relocation address is too big: %#x", o) 595 } 596 } else { 597 if o != int64(int32(o)) && o != int64(uint32(o)) { 598 Diag("non-pc-relative relocation address is too big: %#x", uint64(o)) 599 } 600 } 601 602 fl = int32(o) 603 Ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl)) 604 605 case 8: 606 Ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o)) 607 } 608 } 609 } 610 611 func reloc() { 612 if Debug['v'] != 0 { 613 fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime()) 614 } 615 Bso.Flush() 616 617 for s := Ctxt.Textp; s != nil; s = s.Next { 618 relocsym(s) 619 } 620 for s := datap; s != nil; s = s.Next { 621 relocsym(s) 622 } 623 } 624 625 func dynrelocsym(s *LSym) { 626 if HEADTYPE == obj.Hwindows && Linkmode != LinkExternal { 627 rel := Linklookup(Ctxt, ".rel", 0) 628 if s == rel { 629 return 630 } 631 var r *Reloc 632 var targ *LSym 633 for ri := 0; ri < len(s.R); ri++ { 634 r = &s.R[ri] 635 targ = r.Sym 636 if targ == nil { 637 continue 638 } 639 if !targ.Reachable { 640 Diag("internal inconsistency: dynamic symbol %s is not reachable.", targ.Name) 641 } 642 if r.Sym.Plt == -2 && r.Sym.Got != -2 { // make dynimport JMP table for PE object files. 643 targ.Plt = int32(rel.Size) 644 r.Sym = rel 645 r.Add = int64(targ.Plt) 646 647 // jmp *addr 648 if Thearch.Thechar == '8' { 649 Adduint8(Ctxt, rel, 0xff) 650 Adduint8(Ctxt, rel, 0x25) 651 Addaddr(Ctxt, rel, targ) 652 Adduint8(Ctxt, rel, 0x90) 653 Adduint8(Ctxt, rel, 0x90) 654 } else { 655 Adduint8(Ctxt, rel, 0xff) 656 Adduint8(Ctxt, rel, 0x24) 657 Adduint8(Ctxt, rel, 0x25) 658 addaddrplus4(Ctxt, rel, targ, 0) 659 Adduint8(Ctxt, rel, 0x90) 660 } 661 } else if r.Sym.Plt >= 0 { 662 r.Sym = rel 663 r.Add = int64(targ.Plt) 664 } 665 } 666 667 return 668 } 669 670 var r *Reloc 671 for ri := 0; ri < len(s.R); ri++ { 672 r = &s.R[ri] 673 if r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT || r.Type >= 256 { 674 if r.Sym != nil && !r.Sym.Reachable { 675 Diag("internal inconsistency: dynamic symbol %s is not reachable.", r.Sym.Name) 676 } 677 Thearch.Adddynrel(s, r) 678 } 679 } 680 } 681 682 func dynreloc() { 683 // -d suppresses dynamic loader format, so we may as well not 684 // compute these sections or mark their symbols as reachable. 685 if Debug['d'] != 0 && HEADTYPE != obj.Hwindows { 686 return 687 } 688 if Debug['v'] != 0 { 689 fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime()) 690 } 691 Bso.Flush() 692 693 for s := Ctxt.Textp; s != nil; s = s.Next { 694 dynrelocsym(s) 695 } 696 for s := datap; s != nil; s = s.Next { 697 dynrelocsym(s) 698 } 699 if Iself { 700 elfdynhash() 701 } 702 } 703 704 func blk(start *LSym, addr int64, size int64) { 705 var sym *LSym 706 707 for sym = start; sym != nil; sym = sym.Next { 708 if sym.Type&obj.SSUB == 0 && sym.Value >= addr { 709 break 710 } 711 } 712 713 eaddr := addr + size 714 var ep []byte 715 var p []byte 716 for ; sym != nil; sym = sym.Next { 717 if sym.Type&obj.SSUB != 0 { 718 continue 719 } 720 if sym.Value >= eaddr { 721 break 722 } 723 Ctxt.Cursym = sym 724 if sym.Value < addr { 725 Diag("phase error: addr=%#x but sym=%#x type=%d", int64(addr), int64(sym.Value), sym.Type) 726 errorexit() 727 } 728 729 for ; addr < sym.Value; addr++ { 730 Cput(0) 731 } 732 p = sym.P 733 ep = p[len(sym.P):] 734 for -cap(p) < -cap(ep) { 735 Cput(uint8(p[0])) 736 p = p[1:] 737 } 738 addr += int64(len(sym.P)) 739 for ; addr < sym.Value+sym.Size; addr++ { 740 Cput(0) 741 } 742 if addr != sym.Value+sym.Size { 743 Diag("phase error: addr=%#x value+size=%#x", int64(addr), int64(sym.Value)+sym.Size) 744 errorexit() 745 } 746 747 if sym.Value+sym.Size >= eaddr { 748 break 749 } 750 } 751 752 for ; addr < eaddr; addr++ { 753 Cput(0) 754 } 755 Cflush() 756 } 757 758 func Codeblk(addr int64, size int64) { 759 if Debug['a'] != 0 { 760 fmt.Fprintf(&Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos()) 761 } 762 763 blk(Ctxt.Textp, addr, size) 764 765 /* again for printing */ 766 if Debug['a'] == 0 { 767 return 768 } 769 770 var sym *LSym 771 for sym = Ctxt.Textp; sym != nil; sym = sym.Next { 772 if !sym.Reachable { 773 continue 774 } 775 if sym.Value >= addr { 776 break 777 } 778 } 779 780 eaddr := addr + size 781 var n int64 782 var q []byte 783 for ; sym != nil; sym = sym.Next { 784 if !sym.Reachable { 785 continue 786 } 787 if sym.Value >= eaddr { 788 break 789 } 790 791 if addr < sym.Value { 792 fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr))) 793 for ; addr < sym.Value; addr++ { 794 fmt.Fprintf(&Bso, " %.2x", 0) 795 } 796 fmt.Fprintf(&Bso, "\n") 797 } 798 799 fmt.Fprintf(&Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name) 800 n = sym.Size 801 q = sym.P 802 803 for n >= 16 { 804 fmt.Fprintf(&Bso, "%.6x\t%-20.16I\n", uint64(addr), q) 805 addr += 16 806 q = q[16:] 807 n -= 16 808 } 809 810 if n > 0 { 811 fmt.Fprintf(&Bso, "%.6x\t%-20.*I\n", uint64(addr), int(n), q) 812 } 813 addr += n 814 } 815 816 if addr < eaddr { 817 fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr))) 818 for ; addr < eaddr; addr++ { 819 fmt.Fprintf(&Bso, " %.2x", 0) 820 } 821 } 822 823 Bso.Flush() 824 } 825 826 func Datblk(addr int64, size int64) { 827 if Debug['a'] != 0 { 828 fmt.Fprintf(&Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos()) 829 } 830 831 blk(datap, addr, size) 832 833 /* again for printing */ 834 if Debug['a'] == 0 { 835 return 836 } 837 838 var sym *LSym 839 for sym = datap; sym != nil; sym = sym.Next { 840 if sym.Value >= addr { 841 break 842 } 843 } 844 845 eaddr := addr + size 846 var ep []byte 847 var i int64 848 var p []byte 849 var r *Reloc 850 var rsname string 851 var typ string 852 for ; sym != nil; sym = sym.Next { 853 if sym.Value >= eaddr { 854 break 855 } 856 if addr < sym.Value { 857 fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint64(addr)) 858 addr = sym.Value 859 } 860 861 fmt.Fprintf(&Bso, "%s\n\t%.8x|", sym.Name, uint(addr)) 862 p = sym.P 863 ep = p[len(sym.P):] 864 for -cap(p) < -cap(ep) { 865 if -cap(p) > -cap(sym.P) && int(-cap(p)+cap(sym.P))%16 == 0 { 866 fmt.Fprintf(&Bso, "\n\t%.8x|", uint(addr+int64(-cap(p)+cap(sym.P)))) 867 } 868 fmt.Fprintf(&Bso, " %.2x", p[0]) 869 p = p[1:] 870 } 871 872 addr += int64(len(sym.P)) 873 for ; addr < sym.Value+sym.Size; addr++ { 874 fmt.Fprintf(&Bso, " %.2x", 0) 875 } 876 fmt.Fprintf(&Bso, "\n") 877 878 if Linkmode == LinkExternal { 879 for i = 0; i < int64(len(sym.R)); i++ { 880 r = &sym.R[i] 881 rsname = "" 882 if r.Sym != nil { 883 rsname = r.Sym.Name 884 } 885 typ = "?" 886 switch r.Type { 887 case obj.R_ADDR: 888 typ = "addr" 889 890 case obj.R_PCREL: 891 typ = "pcrel" 892 893 case obj.R_CALL: 894 typ = "call" 895 } 896 897 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)) 898 } 899 } 900 } 901 902 if addr < eaddr { 903 fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint(addr)) 904 } 905 fmt.Fprintf(&Bso, "\t%.8x|\n", uint(eaddr)) 906 } 907 908 func strnput(s string, n int) { 909 for ; n > 0 && s != ""; s = s[1:] { 910 Cput(uint8(s[0])) 911 n-- 912 } 913 914 for n > 0 { 915 Cput(0) 916 n-- 917 } 918 } 919 920 var strdata []*LSym 921 922 func addstrdata1(arg string) { 923 i := strings.Index(arg, "=") 924 if i < 0 { 925 Exitf("-X flag requires argument of the form importpath.name=value") 926 } 927 addstrdata(arg[:i], arg[i+1:]) 928 } 929 930 func addstrdata(name string, value string) { 931 p := fmt.Sprintf("%s.str", name) 932 sp := Linklookup(Ctxt, p, 0) 933 934 Addstring(sp, value) 935 sp.Type = obj.SRODATA 936 937 s := Linklookup(Ctxt, name, 0) 938 s.Size = 0 939 s.Dupok = 1 940 reachable := s.Reachable 941 Addaddr(Ctxt, s, sp) 942 adduintxx(Ctxt, s, uint64(len(value)), Thearch.Ptrsize) 943 944 // addstring, addaddr, etc., mark the symbols as reachable. 945 // In this case that is not necessarily true, so stick to what 946 // we know before entering this function. 947 s.Reachable = reachable 948 949 strdata = append(strdata, s) 950 951 sp.Reachable = reachable 952 } 953 954 func checkstrdata() { 955 for _, s := range strdata { 956 if s.Type == obj.STEXT { 957 Diag("cannot use -X with text symbol %s", s.Name) 958 } else if s.Gotype != nil && s.Gotype.Name != "type.string" { 959 Diag("cannot use -X with non-string symbol %s", s.Name) 960 } 961 } 962 } 963 964 func Addstring(s *LSym, str string) int64 { 965 if s.Type == 0 { 966 s.Type = obj.SNOPTRDATA 967 } 968 s.Reachable = true 969 r := int32(s.Size) 970 n := len(str) + 1 971 if s.Name == ".shstrtab" { 972 elfsetstring(str, int(r)) 973 } 974 Symgrow(Ctxt, s, int64(r)+int64(n)) 975 copy(s.P[r:], str) 976 s.P[int(r)+len(str)] = 0 977 s.Size += int64(n) 978 return int64(r) 979 } 980 981 // addgostring adds str, as a Go string value, to s. symname is the name of the 982 // symbol used to define the string data and must be unique per linked object. 983 func addgostring(s *LSym, symname, str string) { 984 sym := Linklookup(Ctxt, symname, 0) 985 if sym.Type != obj.Sxxx { 986 Diag("duplicate symname in addgostring: %s", symname) 987 } 988 sym.Reachable = true 989 sym.Local = true 990 sym.Type = obj.SRODATA 991 sym.Size = int64(len(str)) 992 sym.P = []byte(str) 993 Addaddr(Ctxt, s, sym) 994 adduint(Ctxt, s, uint64(len(str))) 995 } 996 997 func addinitarrdata(s *LSym) { 998 p := s.Name + ".ptr" 999 sp := Linklookup(Ctxt, p, 0) 1000 sp.Type = obj.SINITARR 1001 sp.Size = 0 1002 sp.Dupok = 1 1003 Addaddr(Ctxt, sp, s) 1004 } 1005 1006 func dosymtype() { 1007 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 1008 if len(s.P) > 0 { 1009 if s.Type == obj.SBSS { 1010 s.Type = obj.SDATA 1011 } 1012 if s.Type == obj.SNOPTRBSS { 1013 s.Type = obj.SNOPTRDATA 1014 } 1015 } 1016 // Create a new entry in the .init_array section that points to the 1017 // library initializer function. 1018 switch Buildmode { 1019 case BuildmodeCArchive, BuildmodeCShared: 1020 if s.Name == INITENTRY { 1021 addinitarrdata(s) 1022 } 1023 } 1024 } 1025 } 1026 1027 func symalign(s *LSym) int32 { 1028 if s.Align != 0 { 1029 return s.Align 1030 } 1031 1032 align := int32(Thearch.Maxalign) 1033 for int64(align) > s.Size && align > 1 { 1034 align >>= 1 1035 } 1036 if align < s.Align { 1037 align = s.Align 1038 } 1039 return align 1040 } 1041 1042 func aligndatsize(datsize int64, s *LSym) int64 { 1043 return Rnd(datsize, int64(symalign(s))) 1044 } 1045 1046 // maxalign returns the maximum required alignment for 1047 // the list of symbols s; the list stops when s->type exceeds type. 1048 func maxalign(s *LSym, type_ int) int32 { 1049 var align int32 1050 1051 max := int32(0) 1052 for ; s != nil && int(s.Type) <= type_; s = s.Next { 1053 align = symalign(s) 1054 if max < align { 1055 max = align 1056 } 1057 } 1058 1059 return max 1060 } 1061 1062 const debugGCProg = false 1063 1064 type GCProg struct { 1065 sym *LSym 1066 w gcprog.Writer 1067 } 1068 1069 func (p *GCProg) Init(name string) { 1070 p.sym = Linklookup(Ctxt, name, 0) 1071 p.w.Init(p.writeByte) 1072 if debugGCProg { 1073 fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name) 1074 p.w.Debug(os.Stderr) 1075 } 1076 } 1077 1078 func (p *GCProg) writeByte(x byte) { 1079 Adduint8(Ctxt, p.sym, x) 1080 } 1081 1082 func (p *GCProg) End(size int64) { 1083 p.w.ZeroUntil(size / int64(Thearch.Ptrsize)) 1084 p.w.End() 1085 if debugGCProg { 1086 fmt.Fprintf(os.Stderr, "ld: end GCProg\n") 1087 } 1088 } 1089 1090 func (p *GCProg) AddSym(s *LSym) { 1091 typ := s.Gotype 1092 // Things without pointers should be in SNOPTRDATA or SNOPTRBSS; 1093 // everything we see should have pointers and should therefore have a type. 1094 if typ == nil { 1095 Diag("missing Go type information for global symbol: %s size %d", s.Name, int(s.Size)) 1096 return 1097 } 1098 1099 ptrsize := int64(Thearch.Ptrsize) 1100 nptr := decodetype_ptrdata(typ) / ptrsize 1101 1102 if debugGCProg { 1103 fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr) 1104 } 1105 1106 if decodetype_usegcprog(typ) == 0 { 1107 // Copy pointers from mask into program. 1108 mask := decodetype_gcmask(typ) 1109 for i := int64(0); i < nptr; i++ { 1110 if (mask[i/8]>>uint(i%8))&1 != 0 { 1111 p.w.Ptr(s.Value/ptrsize + i) 1112 } 1113 } 1114 return 1115 } 1116 1117 // Copy program. 1118 prog := decodetype_gcprog(typ) 1119 p.w.ZeroUntil(s.Value / ptrsize) 1120 p.w.Append(prog[4:], nptr) 1121 } 1122 1123 func growdatsize(datsizep *int64, s *LSym) { 1124 datsize := *datsizep 1125 const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31) 1126 switch { 1127 case s.Size < 0: 1128 Diag("%s: negative size (%d bytes)", s.Name, s.Size) 1129 case s.Size > cutoff: 1130 Diag("%s: symbol too large (%d bytes)", s.Name, s.Size) 1131 case datsize <= cutoff && datsize+s.Size > cutoff: 1132 Diag("%s: too much data (over %d bytes)", s.Name, cutoff) 1133 } 1134 *datsizep = datsize + s.Size 1135 } 1136 1137 func dodata() { 1138 if Debug['v'] != 0 { 1139 fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime()) 1140 } 1141 Bso.Flush() 1142 1143 var last *LSym 1144 datap = nil 1145 1146 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 1147 if !s.Reachable || s.Special != 0 { 1148 continue 1149 } 1150 if obj.STEXT < s.Type && s.Type < obj.SXREF { 1151 if s.Onlist != 0 { 1152 log.Fatalf("symbol %s listed multiple times", s.Name) 1153 } 1154 s.Onlist = 1 1155 if last == nil { 1156 datap = s 1157 } else { 1158 last.Next = s 1159 } 1160 s.Next = nil 1161 last = s 1162 } 1163 } 1164 1165 for s := datap; s != nil; s = s.Next { 1166 if int64(len(s.P)) > s.Size { 1167 Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P)) 1168 } 1169 } 1170 1171 /* 1172 * now that we have the datap list, but before we start 1173 * to assign addresses, record all the necessary 1174 * dynamic relocations. these will grow the relocation 1175 * symbol, which is itself data. 1176 * 1177 * on darwin, we need the symbol table numbers for dynreloc. 1178 */ 1179 if HEADTYPE == obj.Hdarwin { 1180 machosymorder() 1181 } 1182 dynreloc() 1183 1184 /* some symbols may no longer belong in datap (Mach-O) */ 1185 var l **LSym 1186 var s *LSym 1187 for l = &datap; ; { 1188 s = *l 1189 if s == nil { 1190 break 1191 } 1192 1193 if s.Type <= obj.STEXT || obj.SXREF <= s.Type { 1194 *l = s.Next 1195 } else { 1196 l = &s.Next 1197 } 1198 } 1199 1200 *l = nil 1201 1202 datap = listsort(datap, datcmp, listnextp) 1203 1204 if Iself { 1205 // Make .rela and .rela.plt contiguous, the ELF ABI requires this 1206 // and Solaris actually cares. 1207 var relplt *LSym 1208 for l = &datap; *l != nil; l = &(*l).Next { 1209 if (*l).Name == ".rel.plt" || (*l).Name == ".rela.plt" { 1210 relplt = (*l) 1211 *l = (*l).Next 1212 break 1213 } 1214 } 1215 if relplt != nil { 1216 for s = datap; s != nil; s = s.Next { 1217 if s.Name == ".rel" || s.Name == ".rela" { 1218 relplt.Next = s.Next 1219 s.Next = relplt 1220 } 1221 } 1222 } 1223 } 1224 1225 /* 1226 * allocate sections. list is sorted by type, 1227 * so we can just walk it for each piece we want to emit. 1228 * segdata is processed before segtext, because we need 1229 * to see all symbols in the .data and .bss sections in order 1230 * to generate garbage collection information. 1231 */ 1232 1233 /* begin segdata */ 1234 1235 /* skip symbols belonging to segtext */ 1236 s = datap 1237 1238 for ; s != nil && s.Type < obj.SELFSECT; s = s.Next { 1239 } 1240 1241 /* writable ELF sections */ 1242 datsize := int64(0) 1243 1244 var sect *Section 1245 for ; s != nil && s.Type < obj.SELFGOT; s = s.Next { 1246 sect = addsection(&Segdata, s.Name, 06) 1247 sect.Align = symalign(s) 1248 datsize = Rnd(datsize, int64(sect.Align)) 1249 sect.Vaddr = uint64(datsize) 1250 s.Sect = sect 1251 s.Type = obj.SDATA 1252 s.Value = int64(uint64(datsize) - sect.Vaddr) 1253 growdatsize(&datsize, s) 1254 sect.Length = uint64(datsize) - sect.Vaddr 1255 } 1256 1257 /* .got (and .toc on ppc64) */ 1258 if s.Type == obj.SELFGOT { 1259 sect := addsection(&Segdata, ".got", 06) 1260 sect.Align = maxalign(s, obj.SELFGOT) 1261 datsize = Rnd(datsize, int64(sect.Align)) 1262 sect.Vaddr = uint64(datsize) 1263 var toc *LSym 1264 for ; s != nil && s.Type == obj.SELFGOT; s = s.Next { 1265 datsize = aligndatsize(datsize, s) 1266 s.Sect = sect 1267 s.Type = obj.SDATA 1268 s.Value = int64(uint64(datsize) - sect.Vaddr) 1269 1270 // Resolve .TOC. symbol for this object file (ppc64) 1271 toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version)) 1272 1273 if toc != nil { 1274 toc.Sect = sect 1275 toc.Outer = s 1276 toc.Sub = s.Sub 1277 s.Sub = toc 1278 1279 toc.Value = 0x8000 1280 } 1281 1282 growdatsize(&datsize, s) 1283 } 1284 1285 sect.Length = uint64(datsize) - sect.Vaddr 1286 } 1287 1288 /* pointer-free data */ 1289 sect = addsection(&Segdata, ".noptrdata", 06) 1290 1291 sect.Align = maxalign(s, obj.SINITARR-1) 1292 datsize = Rnd(datsize, int64(sect.Align)) 1293 sect.Vaddr = uint64(datsize) 1294 Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect 1295 Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect 1296 for ; s != nil && s.Type < obj.SINITARR; s = s.Next { 1297 datsize = aligndatsize(datsize, s) 1298 s.Sect = sect 1299 s.Type = obj.SDATA 1300 s.Value = int64(uint64(datsize) - sect.Vaddr) 1301 growdatsize(&datsize, s) 1302 } 1303 1304 sect.Length = uint64(datsize) - sect.Vaddr 1305 1306 hasinitarr := Linkshared 1307 1308 /* shared library initializer */ 1309 switch Buildmode { 1310 case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared: 1311 hasinitarr = true 1312 } 1313 1314 if hasinitarr { 1315 sect := addsection(&Segdata, ".init_array", 06) 1316 sect.Align = maxalign(s, obj.SINITARR) 1317 datsize = Rnd(datsize, int64(sect.Align)) 1318 sect.Vaddr = uint64(datsize) 1319 for ; s != nil && s.Type == obj.SINITARR; s = s.Next { 1320 datsize = aligndatsize(datsize, s) 1321 s.Sect = sect 1322 s.Value = int64(uint64(datsize) - sect.Vaddr) 1323 growdatsize(&datsize, s) 1324 } 1325 1326 sect.Length = uint64(datsize) - sect.Vaddr 1327 } 1328 1329 /* data */ 1330 sect = addsection(&Segdata, ".data", 06) 1331 sect.Align = maxalign(s, obj.SBSS-1) 1332 datsize = Rnd(datsize, int64(sect.Align)) 1333 sect.Vaddr = uint64(datsize) 1334 Linklookup(Ctxt, "runtime.data", 0).Sect = sect 1335 Linklookup(Ctxt, "runtime.edata", 0).Sect = sect 1336 var gc GCProg 1337 gc.Init("runtime.gcdata") 1338 for ; s != nil && s.Type < obj.SBSS; s = s.Next { 1339 if s.Type == obj.SINITARR { 1340 Ctxt.Cursym = s 1341 Diag("unexpected symbol type %d", s.Type) 1342 } 1343 1344 s.Sect = sect 1345 s.Type = obj.SDATA 1346 datsize = aligndatsize(datsize, s) 1347 s.Value = int64(uint64(datsize) - sect.Vaddr) 1348 gc.AddSym(s) 1349 growdatsize(&datsize, s) 1350 } 1351 sect.Length = uint64(datsize) - sect.Vaddr 1352 gc.End(int64(sect.Length)) 1353 1354 /* bss */ 1355 sect = addsection(&Segdata, ".bss", 06) 1356 sect.Align = maxalign(s, obj.SNOPTRBSS-1) 1357 datsize = Rnd(datsize, int64(sect.Align)) 1358 sect.Vaddr = uint64(datsize) 1359 Linklookup(Ctxt, "runtime.bss", 0).Sect = sect 1360 Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect 1361 gc = GCProg{} 1362 gc.Init("runtime.gcbss") 1363 for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next { 1364 s.Sect = sect 1365 datsize = aligndatsize(datsize, s) 1366 s.Value = int64(uint64(datsize) - sect.Vaddr) 1367 gc.AddSym(s) 1368 growdatsize(&datsize, s) 1369 } 1370 sect.Length = uint64(datsize) - sect.Vaddr 1371 gc.End(int64(sect.Length)) 1372 1373 /* pointer-free bss */ 1374 sect = addsection(&Segdata, ".noptrbss", 06) 1375 1376 sect.Align = maxalign(s, obj.SNOPTRBSS) 1377 datsize = Rnd(datsize, int64(sect.Align)) 1378 sect.Vaddr = uint64(datsize) 1379 Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect 1380 Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect 1381 for ; s != nil && s.Type == obj.SNOPTRBSS; s = s.Next { 1382 datsize = aligndatsize(datsize, s) 1383 s.Sect = sect 1384 s.Value = int64(uint64(datsize) - sect.Vaddr) 1385 growdatsize(&datsize, s) 1386 } 1387 1388 sect.Length = uint64(datsize) - sect.Vaddr 1389 Linklookup(Ctxt, "runtime.end", 0).Sect = sect 1390 1391 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1392 if datsize != int64(uint32(datsize)) { 1393 Diag("data or bss segment too large") 1394 } 1395 1396 if Iself && Linkmode == LinkExternal && s != nil && s.Type == obj.STLSBSS && HEADTYPE != obj.Hopenbsd { 1397 sect := addsection(&Segdata, ".tbss", 06) 1398 sect.Align = int32(Thearch.Ptrsize) 1399 sect.Vaddr = 0 1400 datsize = 0 1401 for ; s != nil && s.Type == obj.STLSBSS; s = s.Next { 1402 datsize = aligndatsize(datsize, s) 1403 s.Sect = sect 1404 s.Value = int64(uint64(datsize) - sect.Vaddr) 1405 growdatsize(&datsize, s) 1406 } 1407 1408 sect.Length = uint64(datsize) 1409 } else { 1410 // Might be internal linking but still using cgo. 1411 // In that case, the only possible STLSBSS symbol is runtime.tlsg. 1412 // Give it offset 0, because it's the only thing here. 1413 if s != nil && s.Type == obj.STLSBSS && s.Name == "runtime.tlsg" { 1414 s.Value = 0 1415 s = s.Next 1416 } 1417 } 1418 1419 if s != nil { 1420 Ctxt.Cursym = nil 1421 Diag("unexpected symbol type %d for %s", s.Type, s.Name) 1422 } 1423 1424 /* 1425 * We finished data, begin read-only data. 1426 * Not all systems support a separate read-only non-executable data section. 1427 * ELF systems do. 1428 * OS X and Plan 9 do not. 1429 * Windows PE may, but if so we have not implemented it. 1430 * And if we're using external linking mode, the point is moot, 1431 * since it's not our decision; that code expects the sections in 1432 * segtext. 1433 */ 1434 var segro *Segment 1435 if Iself && Linkmode == LinkInternal { 1436 segro = &Segrodata 1437 } else { 1438 segro = &Segtext 1439 } 1440 1441 s = datap 1442 1443 datsize = 0 1444 1445 /* read-only executable ELF, Mach-O sections */ 1446 for ; s != nil && s.Type < obj.STYPE; s = s.Next { 1447 sect = addsection(&Segtext, s.Name, 04) 1448 sect.Align = symalign(s) 1449 datsize = Rnd(datsize, int64(sect.Align)) 1450 sect.Vaddr = uint64(datsize) 1451 s.Sect = sect 1452 s.Type = obj.SRODATA 1453 s.Value = int64(uint64(datsize) - sect.Vaddr) 1454 growdatsize(&datsize, s) 1455 sect.Length = uint64(datsize) - sect.Vaddr 1456 } 1457 1458 /* read-only data */ 1459 sect = addsection(segro, ".rodata", 04) 1460 1461 sect.Align = maxalign(s, obj.STYPELINK-1) 1462 datsize = Rnd(datsize, int64(sect.Align)) 1463 sect.Vaddr = 0 1464 Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect 1465 Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect 1466 for ; s != nil && s.Type < obj.STYPELINK; s = s.Next { 1467 datsize = aligndatsize(datsize, s) 1468 s.Sect = sect 1469 s.Type = obj.SRODATA 1470 s.Value = int64(uint64(datsize) - sect.Vaddr) 1471 growdatsize(&datsize, s) 1472 } 1473 1474 sect.Length = uint64(datsize) - sect.Vaddr 1475 1476 /* typelink */ 1477 sect = addsection(segro, ".typelink", 04) 1478 1479 sect.Align = maxalign(s, obj.STYPELINK) 1480 datsize = Rnd(datsize, int64(sect.Align)) 1481 sect.Vaddr = uint64(datsize) 1482 Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect 1483 Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect 1484 for ; s != nil && s.Type == obj.STYPELINK; s = s.Next { 1485 datsize = aligndatsize(datsize, s) 1486 s.Sect = sect 1487 s.Type = obj.SRODATA 1488 s.Value = int64(uint64(datsize) - sect.Vaddr) 1489 growdatsize(&datsize, s) 1490 } 1491 1492 sect.Length = uint64(datsize) - sect.Vaddr 1493 1494 /* gosymtab */ 1495 sect = addsection(segro, ".gosymtab", 04) 1496 1497 sect.Align = maxalign(s, obj.SPCLNTAB-1) 1498 datsize = Rnd(datsize, int64(sect.Align)) 1499 sect.Vaddr = uint64(datsize) 1500 Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect 1501 Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect 1502 for ; s != nil && s.Type < obj.SPCLNTAB; s = s.Next { 1503 datsize = aligndatsize(datsize, s) 1504 s.Sect = sect 1505 s.Type = obj.SRODATA 1506 s.Value = int64(uint64(datsize) - sect.Vaddr) 1507 growdatsize(&datsize, s) 1508 } 1509 1510 sect.Length = uint64(datsize) - sect.Vaddr 1511 1512 /* gopclntab */ 1513 sect = addsection(segro, ".gopclntab", 04) 1514 1515 sect.Align = maxalign(s, obj.SELFROSECT-1) 1516 datsize = Rnd(datsize, int64(sect.Align)) 1517 sect.Vaddr = uint64(datsize) 1518 Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect 1519 Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect 1520 for ; s != nil && s.Type < obj.SELFROSECT; s = s.Next { 1521 datsize = aligndatsize(datsize, s) 1522 s.Sect = sect 1523 s.Type = obj.SRODATA 1524 s.Value = int64(uint64(datsize) - sect.Vaddr) 1525 growdatsize(&datsize, s) 1526 } 1527 1528 sect.Length = uint64(datsize) - sect.Vaddr 1529 1530 /* read-only ELF, Mach-O sections */ 1531 for ; s != nil && s.Type < obj.SELFSECT; s = s.Next { 1532 sect = addsection(segro, s.Name, 04) 1533 sect.Align = symalign(s) 1534 datsize = Rnd(datsize, int64(sect.Align)) 1535 sect.Vaddr = uint64(datsize) 1536 s.Sect = sect 1537 s.Type = obj.SRODATA 1538 s.Value = int64(uint64(datsize) - sect.Vaddr) 1539 growdatsize(&datsize, s) 1540 sect.Length = uint64(datsize) - sect.Vaddr 1541 } 1542 1543 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1544 if datsize != int64(uint32(datsize)) { 1545 Diag("read-only data segment too large") 1546 } 1547 1548 /* number the sections */ 1549 n := int32(1) 1550 1551 for sect := Segtext.Sect; sect != nil; sect = sect.Next { 1552 sect.Extnum = int16(n) 1553 n++ 1554 } 1555 for sect := Segrodata.Sect; sect != nil; sect = sect.Next { 1556 sect.Extnum = int16(n) 1557 n++ 1558 } 1559 for sect := Segdata.Sect; sect != nil; sect = sect.Next { 1560 sect.Extnum = int16(n) 1561 n++ 1562 } 1563 } 1564 1565 // Add buildid to beginning of text segment, on non-ELF systems. 1566 // Non-ELF binary formats are not always flexible enough to 1567 // give us a place to put the Go build ID. On those systems, we put it 1568 // at the very beginning of the text segment. 1569 // This ``header'' is read by cmd/go. 1570 func textbuildid() { 1571 if Iself || buildid == "" { 1572 return 1573 } 1574 1575 sym := Linklookup(Ctxt, "go.buildid", 0) 1576 sym.Reachable = true 1577 // The \xff is invalid UTF-8, meant to make it less likely 1578 // to find one of these accidentally. 1579 data := "\xff Go build ID: " + strconv.Quote(buildid) + "\n \xff" 1580 sym.Type = obj.STEXT 1581 sym.P = []byte(data) 1582 sym.Size = int64(len(sym.P)) 1583 1584 sym.Next = Ctxt.Textp 1585 Ctxt.Textp = sym 1586 } 1587 1588 // assign addresses to text 1589 func textaddress() { 1590 var sub *LSym 1591 1592 addsection(&Segtext, ".text", 05) 1593 1594 // Assign PCs in text segment. 1595 // Could parallelize, by assigning to text 1596 // and then letting threads copy down, but probably not worth it. 1597 sect := Segtext.Sect 1598 1599 sect.Align = int32(Funcalign) 1600 Linklookup(Ctxt, "runtime.text", 0).Sect = sect 1601 Linklookup(Ctxt, "runtime.etext", 0).Sect = sect 1602 va := uint64(INITTEXT) 1603 sect.Vaddr = va 1604 for sym := Ctxt.Textp; sym != nil; sym = sym.Next { 1605 sym.Sect = sect 1606 if sym.Type&obj.SSUB != 0 { 1607 continue 1608 } 1609 if sym.Align != 0 { 1610 va = uint64(Rnd(int64(va), int64(sym.Align))) 1611 } else { 1612 va = uint64(Rnd(int64(va), int64(Funcalign))) 1613 } 1614 sym.Value = 0 1615 for sub = sym; sub != nil; sub = sub.Sub { 1616 sub.Value += int64(va) 1617 } 1618 if sym.Size == 0 && sym.Sub != nil { 1619 Ctxt.Cursym = sym 1620 } 1621 if sym.Size < MINFUNC { 1622 va += MINFUNC // spacing required for findfunctab 1623 } else { 1624 va += uint64(sym.Size) 1625 } 1626 } 1627 1628 sect.Length = va - sect.Vaddr 1629 } 1630 1631 // assign addresses 1632 func address() { 1633 va := uint64(INITTEXT) 1634 Segtext.Rwx = 05 1635 Segtext.Vaddr = va 1636 Segtext.Fileoff = uint64(HEADR) 1637 for s := Segtext.Sect; s != nil; s = s.Next { 1638 va = uint64(Rnd(int64(va), int64(s.Align))) 1639 s.Vaddr = va 1640 va += s.Length 1641 } 1642 1643 Segtext.Length = va - uint64(INITTEXT) 1644 Segtext.Filelen = Segtext.Length 1645 if HEADTYPE == obj.Hnacl { 1646 va += 32 // room for the "halt sled" 1647 } 1648 1649 if Segrodata.Sect != nil { 1650 // align to page boundary so as not to mix 1651 // rodata and executable text. 1652 va = uint64(Rnd(int64(va), int64(INITRND))) 1653 1654 Segrodata.Rwx = 04 1655 Segrodata.Vaddr = va 1656 Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff 1657 Segrodata.Filelen = 0 1658 for s := Segrodata.Sect; s != nil; s = s.Next { 1659 va = uint64(Rnd(int64(va), int64(s.Align))) 1660 s.Vaddr = va 1661 va += s.Length 1662 } 1663 1664 Segrodata.Length = va - Segrodata.Vaddr 1665 Segrodata.Filelen = Segrodata.Length 1666 } 1667 1668 va = uint64(Rnd(int64(va), int64(INITRND))) 1669 Segdata.Rwx = 06 1670 Segdata.Vaddr = va 1671 Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff 1672 Segdata.Filelen = 0 1673 if HEADTYPE == obj.Hwindows { 1674 Segdata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN)) 1675 } 1676 if HEADTYPE == obj.Hplan9 { 1677 Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen 1678 } 1679 var data *Section 1680 var noptr *Section 1681 var bss *Section 1682 var noptrbss *Section 1683 var vlen int64 1684 for s := Segdata.Sect; s != nil; s = s.Next { 1685 vlen = int64(s.Length) 1686 if s.Next != nil { 1687 vlen = int64(s.Next.Vaddr - s.Vaddr) 1688 } 1689 s.Vaddr = va 1690 va += uint64(vlen) 1691 Segdata.Length = va - Segdata.Vaddr 1692 if s.Name == ".data" { 1693 data = s 1694 } 1695 if s.Name == ".noptrdata" { 1696 noptr = s 1697 } 1698 if s.Name == ".bss" { 1699 bss = s 1700 } 1701 if s.Name == ".noptrbss" { 1702 noptrbss = s 1703 } 1704 } 1705 1706 Segdata.Filelen = bss.Vaddr - Segdata.Vaddr 1707 1708 text := Segtext.Sect 1709 var rodata *Section 1710 if Segrodata.Sect != nil { 1711 rodata = Segrodata.Sect 1712 } else { 1713 rodata = text.Next 1714 } 1715 typelink := rodata.Next 1716 symtab := typelink.Next 1717 pclntab := symtab.Next 1718 1719 var sub *LSym 1720 for sym := datap; sym != nil; sym = sym.Next { 1721 Ctxt.Cursym = sym 1722 if sym.Sect != nil { 1723 sym.Value += int64(sym.Sect.Vaddr) 1724 } 1725 for sub = sym.Sub; sub != nil; sub = sub.Sub { 1726 sub.Value += sym.Value 1727 } 1728 } 1729 1730 if Buildmode == BuildmodeShared { 1731 s := Linklookup(Ctxt, "go.link.abihashbytes", 0) 1732 sectSym := Linklookup(Ctxt, ".note.go.abihash", 0) 1733 s.Sect = sectSym.Sect 1734 s.Value = int64(sectSym.Sect.Vaddr + 16) 1735 } 1736 1737 xdefine("runtime.text", obj.STEXT, int64(text.Vaddr)) 1738 xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length)) 1739 xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr)) 1740 xdefine("runtime.erodata", obj.SRODATA, int64(rodata.Vaddr+rodata.Length)) 1741 xdefine("runtime.typelink", obj.SRODATA, int64(typelink.Vaddr)) 1742 xdefine("runtime.etypelink", obj.SRODATA, int64(typelink.Vaddr+typelink.Length)) 1743 1744 sym := Linklookup(Ctxt, "runtime.gcdata", 0) 1745 sym.Local = true 1746 xdefine("runtime.egcdata", obj.SRODATA, Symaddr(sym)+sym.Size) 1747 Linklookup(Ctxt, "runtime.egcdata", 0).Sect = sym.Sect 1748 1749 sym = Linklookup(Ctxt, "runtime.gcbss", 0) 1750 sym.Local = true 1751 xdefine("runtime.egcbss", obj.SRODATA, Symaddr(sym)+sym.Size) 1752 Linklookup(Ctxt, "runtime.egcbss", 0).Sect = sym.Sect 1753 1754 xdefine("runtime.symtab", obj.SRODATA, int64(symtab.Vaddr)) 1755 xdefine("runtime.esymtab", obj.SRODATA, int64(symtab.Vaddr+symtab.Length)) 1756 xdefine("runtime.pclntab", obj.SRODATA, int64(pclntab.Vaddr)) 1757 xdefine("runtime.epclntab", obj.SRODATA, int64(pclntab.Vaddr+pclntab.Length)) 1758 xdefine("runtime.noptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr)) 1759 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length)) 1760 xdefine("runtime.bss", obj.SBSS, int64(bss.Vaddr)) 1761 xdefine("runtime.ebss", obj.SBSS, int64(bss.Vaddr+bss.Length)) 1762 xdefine("runtime.data", obj.SDATA, int64(data.Vaddr)) 1763 xdefine("runtime.edata", obj.SDATA, int64(data.Vaddr+data.Length)) 1764 xdefine("runtime.noptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr)) 1765 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length)) 1766 xdefine("runtime.end", obj.SBSS, int64(Segdata.Vaddr+Segdata.Length)) 1767 }