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