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