github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/ld/data.c (about) 1 // Inferno utils/8l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Data layout and relocation. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 #include "../ld/elf.h" 36 #include "../ld/macho.h" 37 #include "../ld/pe.h" 38 #include "../../runtime/mgc0.h" 39 40 void dynreloc(void); 41 42 /* 43 * divide-and-conquer list-link 44 * sort of LSym* structures. 45 * Used for the data block. 46 */ 47 int 48 datcmp(LSym *s1, LSym *s2) 49 { 50 if(s1->type != s2->type) 51 return (int)s1->type - (int)s2->type; 52 // For ppc64, we want to interleave the .got and .toc sections 53 // from input files. Both are type SELFGOT, so in that case 54 // fall through to the name comparison (conveniently, .got 55 // sorts before .toc). 56 if(s1->type != SELFGOT && s1->size != s2->size) { 57 if(s1->size < s2->size) 58 return -1; 59 return +1; 60 } 61 return strcmp(s1->name, s2->name); 62 } 63 64 LSym* 65 listsort(LSym *l, int (*cmp)(LSym*, LSym*), int off) 66 { 67 LSym *l1, *l2, *le; 68 #define NEXT(l) (*(LSym**)((char*)(l)+off)) 69 70 if(l == 0 || NEXT(l) == 0) 71 return l; 72 73 l1 = l; 74 l2 = l; 75 for(;;) { 76 l2 = NEXT(l2); 77 if(l2 == 0) 78 break; 79 l2 = NEXT(l2); 80 if(l2 == 0) 81 break; 82 l1 = NEXT(l1); 83 } 84 85 l2 = NEXT(l1); 86 NEXT(l1) = 0; 87 l1 = listsort(l, cmp, off); 88 l2 = listsort(l2, cmp, off); 89 90 /* set up lead element */ 91 if(cmp(l1, l2) < 0) { 92 l = l1; 93 l1 = NEXT(l1); 94 } else { 95 l = l2; 96 l2 = NEXT(l2); 97 } 98 le = l; 99 100 for(;;) { 101 if(l1 == 0) { 102 while(l2) { 103 NEXT(le) = l2; 104 le = l2; 105 l2 = NEXT(l2); 106 } 107 NEXT(le) = 0; 108 break; 109 } 110 if(l2 == 0) { 111 while(l1) { 112 NEXT(le) = l1; 113 le = l1; 114 l1 = NEXT(l1); 115 } 116 break; 117 } 118 if(cmp(l1, l2) < 0) { 119 NEXT(le) = l1; 120 le = l1; 121 l1 = NEXT(l1); 122 } else { 123 NEXT(le) = l2; 124 le = l2; 125 l2 = NEXT(l2); 126 } 127 } 128 NEXT(le) = 0; 129 return l; 130 131 #undef NEXT 132 } 133 134 void 135 relocsym(LSym *s) 136 { 137 Reloc *r; 138 LSym *rs; 139 int16 i16; 140 int32 i, off, siz, fl; 141 vlong o; 142 uchar *cast; 143 144 ctxt->cursym = s; 145 for(r=s->r; r<s->r+s->nr; r++) { 146 r->done = 1; 147 off = r->off; 148 siz = r->siz; 149 if(off < 0 || off+siz > s->np) { 150 diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np); 151 continue; 152 } 153 if(r->sym != S && ((r->sym->type & (SMASK | SHIDDEN)) == 0 || (r->sym->type & SMASK) == SXREF)) { 154 diag("%s: not defined", r->sym->name); 155 continue; 156 } 157 if(r->type >= 256) 158 continue; 159 if(r->siz == 0) // informational relocation - no work to do 160 continue; 161 162 // Solaris needs the ability to reference dynimport symbols. 163 if(HEADTYPE != Hsolaris && r->sym != S && r->sym->type == SDYNIMPORT) 164 diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type); 165 if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable) 166 diag("unreachable sym in relocation: %s %s", s->name, r->sym->name); 167 168 // Android emulates runtime.tlsg as a regular variable. 169 if (r->type == R_TLS && strcmp(goos, "android") == 0) 170 r->type = R_ADDR; 171 172 switch(r->type) { 173 default: 174 o = 0; 175 if(archreloc(r, s, &o) < 0) 176 diag("unknown reloc %d", r->type); 177 break; 178 case R_TLS: 179 if(linkmode == LinkInternal && iself && thechar == '5') { 180 // On ELF ARM, the thread pointer is 8 bytes before 181 // the start of the thread-local data block, so add 8 182 // to the actual TLS offset (r->sym->value). 183 // This 8 seems to be a fundamental constant of 184 // ELF on ARM (or maybe Glibc on ARM); it is not 185 // related to the fact that our own TLS storage happens 186 // to take up 8 bytes. 187 o = 8 + r->sym->value; 188 break; 189 } 190 r->done = 0; 191 o = 0; 192 if(thechar != '6') 193 o = r->add; 194 break; 195 case R_TLS_LE: 196 if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) { 197 r->done = 0; 198 r->sym = ctxt->tlsg; 199 r->xsym = ctxt->tlsg; 200 r->xadd = r->add; 201 o = 0; 202 if(thechar != '6') 203 o = r->add; 204 break; 205 } 206 o = ctxt->tlsoffset + r->add; 207 break; 208 209 case R_TLS_IE: 210 if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) { 211 r->done = 0; 212 r->sym = ctxt->tlsg; 213 r->xsym = ctxt->tlsg; 214 r->xadd = r->add; 215 o = 0; 216 if(thechar != '6') 217 o = r->add; 218 break; 219 } 220 if(iself || ctxt->headtype == Hplan9) 221 o = ctxt->tlsoffset + r->add; 222 else if(ctxt->headtype == Hwindows) 223 o = r->add; 224 else 225 sysfatal("unexpected R_TLS_IE relocation for %s", headstr(ctxt->headtype)); 226 break; 227 case R_ADDR: 228 if(linkmode == LinkExternal && r->sym->type != SCONST) { 229 r->done = 0; 230 231 // set up addend for eventual relocation via outer symbol. 232 rs = r->sym; 233 r->xadd = r->add; 234 while(rs->outer != nil) { 235 r->xadd += symaddr(rs) - symaddr(rs->outer); 236 rs = rs->outer; 237 } 238 if(rs->type != SHOSTOBJ && rs->type != SDYNIMPORT && rs->sect == nil) 239 diag("missing section for %s", rs->name); 240 r->xsym = rs; 241 242 o = r->xadd; 243 if(iself) { 244 if(thechar == '6') 245 o = 0; 246 } else if(HEADTYPE == Hdarwin) { 247 if(rs->type != SHOSTOBJ) 248 o += symaddr(rs); 249 } else { 250 diag("unhandled pcrel relocation for %s", headstring); 251 } 252 break; 253 } 254 o = symaddr(r->sym) + r->add; 255 256 // On amd64, 4-byte offsets will be sign-extended, so it is impossible to 257 // access more than 2GB of static data; fail at link time is better than 258 // fail at runtime. See http://golang.org/issue/7980. 259 // Instead of special casing only amd64, we treat this as an error on all 260 // 64-bit architectures so as to be future-proof. 261 if((int32)o < 0 && PtrSize > 4 && siz == 4) { 262 diag("non-pc-relative relocation address is too big: %#llux", o); 263 errorexit(); 264 } 265 break; 266 case R_CALL: 267 case R_PCREL: 268 // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. 269 if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != ctxt->cursym->sect) { 270 r->done = 0; 271 272 // set up addend for eventual relocation via outer symbol. 273 rs = r->sym; 274 r->xadd = r->add; 275 while(rs->outer != nil) { 276 r->xadd += symaddr(rs) - symaddr(rs->outer); 277 rs = rs->outer; 278 } 279 r->xadd -= r->siz; // relative to address after the relocated chunk 280 if(rs->type != SHOSTOBJ && rs->type != SDYNIMPORT && rs->sect == nil) 281 diag("missing section for %s", rs->name); 282 r->xsym = rs; 283 284 o = r->xadd; 285 if(iself) { 286 if(thechar == '6') 287 o = 0; 288 } else if(HEADTYPE == Hdarwin) { 289 if(r->type == R_CALL) { 290 if(rs->type != SHOSTOBJ) 291 o += symaddr(rs) - rs->sect->vaddr; 292 o -= r->off; // relative to section offset, not symbol 293 } else { 294 o += r->siz; 295 } 296 } else { 297 diag("unhandled pcrel relocation for %s", headstring); 298 } 299 break; 300 } 301 o = 0; 302 if(r->sym) 303 o += symaddr(r->sym); 304 // NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c 305 // compiler. The expression s->value + r->off + r->siz is int32 + int32 + 306 // uchar, and Plan 9 8c incorrectly treats the expression as type uint32 307 // instead of int32, causing incorrect values when sign extended for adding 308 // to o. The bug only occurs on Plan 9, because this C program is compiled by 309 // the standard host compiler (gcc on most other systems). 310 o += r->add - (s->value + r->off + (int32)r->siz); 311 break; 312 case R_SIZE: 313 o = r->sym->size + r->add; 314 break; 315 } 316 if(r->variant != RV_NONE) 317 o = archrelocvariant(r, s, o); 318 //print("relocate %s %#llux (%#llux+%#llux, size %d) => %s %#llux +%#llx [%llx]\n", s->name, (uvlong)(s->value+off), (uvlong)s->value, (uvlong)r->off, r->siz, r->sym ? r->sym->name : "<nil>", (uvlong)symaddr(r->sym), (vlong)r->add, (vlong)o); 319 switch(siz) { 320 default: 321 ctxt->cursym = s; 322 diag("bad reloc size %#ux for %s", siz, r->sym->name); 323 case 1: 324 // TODO(rsc): Remove. 325 s->p[off] = (int8)o; 326 break; 327 case 2: 328 if(o != (int16)o) 329 diag("relocation address is too big: %#llx", o); 330 i16 = o; 331 cast = (uchar*)&i16; 332 for(i=0; i<2; i++) 333 s->p[off+i] = cast[inuxi2[i]]; 334 break; 335 case 4: 336 if(r->type == R_PCREL || r->type == R_CALL) { 337 if(o != (int32)o) 338 diag("pc-relative relocation address is too big: %#llx", o); 339 } else { 340 if(o != (int32)o && o != (uint32)o) 341 diag("non-pc-relative relocation address is too big: %#llux", o); 342 } 343 fl = o; 344 cast = (uchar*)&fl; 345 for(i=0; i<4; i++) 346 s->p[off+i] = cast[inuxi4[i]]; 347 break; 348 case 8: 349 cast = (uchar*)&o; 350 for(i=0; i<8; i++) 351 s->p[off+i] = cast[inuxi8[i]]; 352 break; 353 } 354 } 355 } 356 357 void 358 reloc(void) 359 { 360 LSym *s; 361 362 if(debug['v']) 363 Bprint(&bso, "%5.2f reloc\n", cputime()); 364 Bflush(&bso); 365 366 for(s=ctxt->textp; s!=S; s=s->next) 367 relocsym(s); 368 for(s=datap; s!=S; s=s->next) 369 relocsym(s); 370 } 371 372 void 373 dynrelocsym(LSym *s) 374 { 375 Reloc *r; 376 377 if(HEADTYPE == Hwindows) { 378 LSym *rel, *targ; 379 380 rel = linklookup(ctxt, ".rel", 0); 381 if(s == rel) 382 return; 383 for(r=s->r; r<s->r+s->nr; r++) { 384 targ = r->sym; 385 if(targ == nil) 386 continue; 387 if(!targ->reachable) 388 diag("internal inconsistency: dynamic symbol %s is not reachable.", targ->name); 389 if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. 390 targ->plt = rel->size; 391 r->sym = rel; 392 r->add = targ->plt; 393 394 // jmp *addr 395 if(thechar == '8') { 396 adduint8(ctxt, rel, 0xff); 397 adduint8(ctxt, rel, 0x25); 398 addaddr(ctxt, rel, targ); 399 adduint8(ctxt, rel, 0x90); 400 adduint8(ctxt, rel, 0x90); 401 } else { 402 adduint8(ctxt, rel, 0xff); 403 adduint8(ctxt, rel, 0x24); 404 adduint8(ctxt, rel, 0x25); 405 addaddrplus4(ctxt, rel, targ, 0); 406 adduint8(ctxt, rel, 0x90); 407 } 408 } else if(r->sym->plt >= 0) { 409 r->sym = rel; 410 r->add = targ->plt; 411 } 412 } 413 return; 414 } 415 416 for(r=s->r; r<s->r+s->nr; r++) { 417 if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) { 418 if(r->sym != S && !r->sym->reachable) 419 diag("internal inconsistency: dynamic symbol %s is not reachable.", r->sym->name); 420 adddynrel(s, r); 421 } 422 } 423 } 424 425 void 426 dynreloc(void) 427 { 428 LSym *s; 429 430 // -d suppresses dynamic loader format, so we may as well not 431 // compute these sections or mark their symbols as reachable. 432 if(debug['d'] && HEADTYPE != Hwindows) 433 return; 434 if(debug['v']) 435 Bprint(&bso, "%5.2f reloc\n", cputime()); 436 Bflush(&bso); 437 438 for(s=ctxt->textp; s!=S; s=s->next) 439 dynrelocsym(s); 440 for(s=datap; s!=S; s=s->next) 441 dynrelocsym(s); 442 if(iself) 443 elfdynhash(); 444 } 445 446 static void 447 blk(LSym *start, int64 addr, int64 size) 448 { 449 LSym *sym; 450 int64 eaddr; 451 uchar *p, *ep; 452 453 for(sym = start; sym != nil; sym = sym->next) 454 if(!(sym->type&SSUB) && sym->value >= addr) 455 break; 456 457 eaddr = addr+size; 458 for(; sym != nil; sym = sym->next) { 459 if(sym->type&SSUB) 460 continue; 461 if(sym->value >= eaddr) 462 break; 463 ctxt->cursym = sym; 464 if(sym->value < addr) { 465 diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type); 466 errorexit(); 467 } 468 for(; addr < sym->value; addr++) 469 cput(0); 470 p = sym->p; 471 ep = p + sym->np; 472 while(p < ep) 473 cput(*p++); 474 addr += sym->np; 475 for(; addr < sym->value+sym->size; addr++) 476 cput(0); 477 if(addr != sym->value+sym->size) { 478 diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size); 479 errorexit(); 480 } 481 if(sym->value+sym->size >= eaddr) 482 break; 483 } 484 485 for(; addr < eaddr; addr++) 486 cput(0); 487 cflush(); 488 } 489 490 void 491 codeblk(int64 addr, int64 size) 492 { 493 LSym *sym; 494 int64 eaddr, n; 495 uchar *q; 496 497 if(debug['a']) 498 Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos()); 499 500 blk(ctxt->textp, addr, size); 501 502 /* again for printing */ 503 if(!debug['a']) 504 return; 505 506 for(sym = ctxt->textp; sym != nil; sym = sym->next) { 507 if(!sym->reachable) 508 continue; 509 if(sym->value >= addr) 510 break; 511 } 512 513 eaddr = addr + size; 514 for(; sym != nil; sym = sym->next) { 515 if(!sym->reachable) 516 continue; 517 if(sym->value >= eaddr) 518 break; 519 520 if(addr < sym->value) { 521 Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr); 522 for(; addr < sym->value; addr++) 523 Bprint(&bso, " %.2ux", 0); 524 Bprint(&bso, "\n"); 525 } 526 527 Bprint(&bso, "%.6llux\t%-20s\n", (vlong)addr, sym->name); 528 n = sym->size; 529 q = sym->p; 530 531 while(n >= 16) { 532 Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q); 533 addr += 16; 534 q += 16; 535 n -= 16; 536 } 537 if(n > 0) 538 Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q); 539 addr += n; 540 } 541 542 if(addr < eaddr) { 543 Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr); 544 for(; addr < eaddr; addr++) 545 Bprint(&bso, " %.2ux", 0); 546 } 547 Bflush(&bso); 548 } 549 550 void 551 datblk(int64 addr, int64 size) 552 { 553 LSym *sym; 554 int64 i, eaddr; 555 uchar *p, *ep; 556 char *typ, *rsname; 557 Reloc *r; 558 559 if(debug['a']) 560 Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos()); 561 562 blk(datap, addr, size); 563 564 /* again for printing */ 565 if(!debug['a']) 566 return; 567 568 for(sym = datap; sym != nil; sym = sym->next) 569 if(sym->value >= addr) 570 break; 571 572 eaddr = addr + size; 573 for(; sym != nil; sym = sym->next) { 574 if(sym->value >= eaddr) 575 break; 576 if(addr < sym->value) { 577 Bprint(&bso, "\t%.8ux| 00 ...\n", addr); 578 addr = sym->value; 579 } 580 Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr); 581 p = sym->p; 582 ep = p + sym->np; 583 while(p < ep) { 584 if(p > sym->p && (int)(p-sym->p)%16 == 0) 585 Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p))); 586 Bprint(&bso, " %.2ux", *p++); 587 } 588 addr += sym->np; 589 for(; addr < sym->value+sym->size; addr++) 590 Bprint(&bso, " %.2ux", 0); 591 Bprint(&bso, "\n"); 592 593 if(linkmode == LinkExternal) { 594 for(i=0; i<sym->nr; i++) { 595 r = &sym->r[i]; 596 rsname = ""; 597 if(r->sym) 598 rsname = r->sym->name; 599 typ = "?"; 600 switch(r->type) { 601 case R_ADDR: 602 typ = "addr"; 603 break; 604 case R_PCREL: 605 typ = "pcrel"; 606 break; 607 case R_CALL: 608 typ = "call"; 609 break; 610 } 611 Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n", 612 (uint)(sym->value+r->off), r->siz, typ, rsname, (vlong)r->add, (vlong)(r->sym->value+r->add)); 613 } 614 } 615 } 616 617 if(addr < eaddr) 618 Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr); 619 Bprint(&bso, "\t%.8ux|\n", (uint)eaddr); 620 } 621 622 void 623 strnput(char *s, int n) 624 { 625 for(; n > 0 && *s; s++) { 626 cput(*s); 627 n--; 628 } 629 while(n > 0) { 630 cput(0); 631 n--; 632 } 633 } 634 635 void 636 addstrdata(char *name, char *value) 637 { 638 LSym *s, *sp; 639 char *p; 640 uchar reachable; 641 642 p = smprint("%s.str", name); 643 sp = linklookup(ctxt, p, 0); 644 free(p); 645 addstring(sp, value); 646 sp->type = SRODATA; 647 648 s = linklookup(ctxt, name, 0); 649 s->size = 0; 650 s->dupok = 1; 651 reachable = s->reachable; 652 addaddr(ctxt, s, sp); 653 adduintxx(ctxt, s, strlen(value), PtrSize); 654 655 // addstring, addaddr, etc., mark the symbols as reachable. 656 // In this case that is not necessarily true, so stick to what 657 // we know before entering this function. 658 s->reachable = reachable; 659 sp->reachable = reachable; 660 } 661 662 vlong 663 addstring(LSym *s, char *str) 664 { 665 int n; 666 int32 r; 667 668 if(s->type == 0) 669 s->type = SNOPTRDATA; 670 s->reachable = 1; 671 r = s->size; 672 n = strlen(str)+1; 673 if(strcmp(s->name, ".shstrtab") == 0) 674 elfsetstring(str, r); 675 symgrow(ctxt, s, r+n); 676 memmove(s->p+r, str, n); 677 s->size += n; 678 return r; 679 } 680 681 void 682 dosymtype(void) 683 { 684 LSym *s; 685 686 for(s = ctxt->allsym; s != nil; s = s->allsym) { 687 if(s->np > 0) { 688 if(s->type == SBSS) 689 s->type = SDATA; 690 if(s->type == SNOPTRBSS) 691 s->type = SNOPTRDATA; 692 } 693 } 694 } 695 696 static int32 697 symalign(LSym *s) 698 { 699 int32 align; 700 701 if(s->align != 0) 702 return s->align; 703 704 align = MaxAlign; 705 while(align > s->size && align > 1) 706 align >>= 1; 707 if(align < s->align) 708 align = s->align; 709 return align; 710 } 711 712 static vlong 713 aligndatsize(vlong datsize, LSym *s) 714 { 715 return rnd(datsize, symalign(s)); 716 } 717 718 // maxalign returns the maximum required alignment for 719 // the list of symbols s; the list stops when s->type exceeds type. 720 static int32 721 maxalign(LSym *s, int type) 722 { 723 int32 align, max; 724 725 max = 0; 726 for(; s != S && s->type <= type; s = s->next) { 727 align = symalign(s); 728 if(max < align) 729 max = align; 730 } 731 return max; 732 } 733 734 // Helper object for building GC type programs. 735 typedef struct ProgGen ProgGen; 736 struct ProgGen 737 { 738 LSym* s; 739 int32 datasize; 740 uint8 data[256/PointersPerByte]; 741 vlong pos; 742 }; 743 744 static void 745 proggeninit(ProgGen *g, LSym *s) 746 { 747 g->s = s; 748 g->datasize = 0; 749 g->pos = 0; 750 memset(g->data, 0, sizeof(g->data)); 751 } 752 753 static void 754 proggenemit(ProgGen *g, uint8 v) 755 { 756 adduint8(ctxt, g->s, v); 757 } 758 759 // Writes insData block from g->data. 760 static void 761 proggendataflush(ProgGen *g) 762 { 763 int32 i, s; 764 765 if(g->datasize == 0) 766 return; 767 proggenemit(g, insData); 768 proggenemit(g, g->datasize); 769 s = (g->datasize + PointersPerByte - 1)/PointersPerByte; 770 for(i = 0; i < s; i++) 771 proggenemit(g, g->data[i]); 772 g->datasize = 0; 773 memset(g->data, 0, sizeof(g->data)); 774 } 775 776 static void 777 proggendata(ProgGen *g, uint8 d) 778 { 779 g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer); 780 g->datasize++; 781 if(g->datasize == 255) 782 proggendataflush(g); 783 } 784 785 // Skip v bytes due to alignment, etc. 786 static void 787 proggenskip(ProgGen *g, vlong off, vlong v) 788 { 789 vlong i; 790 791 for(i = off; i < off+v; i++) { 792 if((i%PtrSize) == 0) 793 proggendata(g, BitsScalar); 794 } 795 } 796 797 // Emit insArray instruction. 798 static void 799 proggenarray(ProgGen *g, vlong len) 800 { 801 int32 i; 802 803 proggendataflush(g); 804 proggenemit(g, insArray); 805 for(i = 0; i < PtrSize; i++, len >>= 8) 806 proggenemit(g, len); 807 } 808 809 static void 810 proggenarrayend(ProgGen *g) 811 { 812 proggendataflush(g); 813 proggenemit(g, insArrayEnd); 814 } 815 816 static void 817 proggenfini(ProgGen *g, vlong size) 818 { 819 proggenskip(g, g->pos, size - g->pos); 820 proggendataflush(g); 821 proggenemit(g, insEnd); 822 } 823 824 825 // This function generates GC pointer info for global variables. 826 static void 827 proggenaddsym(ProgGen *g, LSym *s) 828 { 829 LSym *gcprog; 830 uint8 *mask; 831 vlong i, size; 832 833 if(s->size == 0) 834 return; 835 836 // Skip alignment hole from the previous symbol. 837 proggenskip(g, g->pos, s->value - g->pos); 838 g->pos += s->value - g->pos; 839 840 // The test for names beginning with . here is meant 841 // to keep .dynamic and .dynsym from turning up as 842 // conservative symbols. They should be marked SELFSECT 843 // and not SDATA, but sometimes that doesn't happen. 844 // Leave debugging the SDATA issue for the Go rewrite. 845 846 if(s->gotype == nil && s->size >= PtrSize && s->name[0] != '.') { 847 // conservative scan 848 diag("missing Go type information for global symbol: %s size %d", s->name, (int)s->size); 849 if((s->size%PtrSize) || (g->pos%PtrSize)) 850 diag("proggenaddsym: unaligned conservative symbol %s: size=%lld pos=%lld", 851 s->name, s->size, g->pos); 852 size = (s->size+PtrSize-1)/PtrSize*PtrSize; 853 if(size < 32*PtrSize) { 854 // Emit small symbols as data. 855 for(i = 0; i < size/PtrSize; i++) 856 proggendata(g, BitsPointer); 857 } else { 858 // Emit large symbols as array. 859 proggenarray(g, size/PtrSize); 860 proggendata(g, BitsPointer); 861 proggenarrayend(g); 862 } 863 g->pos = s->value + size; 864 } else if(s->gotype == nil || decodetype_noptr(s->gotype) || s->size < PtrSize || s->name[0] == '.') { 865 // no scan 866 if(s->size < 32*PtrSize) { 867 // Emit small symbols as data. 868 // This case also handles unaligned and tiny symbols, so tread carefully. 869 for(i = s->value; i < s->value+s->size; i++) { 870 if((i%PtrSize) == 0) 871 proggendata(g, BitsScalar); 872 } 873 } else { 874 // Emit large symbols as array. 875 if((s->size%PtrSize) || (g->pos%PtrSize)) 876 diag("proggenaddsym: unaligned noscan symbol %s: size=%lld pos=%lld", 877 s->name, s->size, g->pos); 878 proggenarray(g, s->size/PtrSize); 879 proggendata(g, BitsScalar); 880 proggenarrayend(g); 881 } 882 g->pos = s->value + s->size; 883 } else if(decodetype_usegcprog(s->gotype)) { 884 // gc program, copy directly 885 proggendataflush(g); 886 gcprog = decodetype_gcprog(s->gotype); 887 size = decodetype_size(s->gotype); 888 if((size%PtrSize) || (g->pos%PtrSize)) 889 diag("proggenaddsym: unaligned gcprog symbol %s: size=%lld pos=%lld", 890 s->name, s->size, g->pos); 891 for(i = 0; i < gcprog->np-1; i++) 892 proggenemit(g, gcprog->p[i]); 893 g->pos = s->value + size; 894 } else { 895 // gc mask, it's small so emit as data 896 mask = decodetype_gcmask(s->gotype); 897 size = decodetype_size(s->gotype); 898 if((size%PtrSize) || (g->pos%PtrSize)) 899 diag("proggenaddsym: unaligned gcmask symbol %s: size=%lld pos=%lld", 900 s->name, s->size, g->pos); 901 for(i = 0; i < size; i += PtrSize) 902 proggendata(g, (mask[i/PtrSize/2]>>((i/PtrSize%2)*4+2))&BitsMask); 903 g->pos = s->value + size; 904 } 905 } 906 907 void 908 growdatsize(vlong *datsizep, LSym *s) 909 { 910 vlong datsize; 911 912 datsize = *datsizep; 913 if(s->size < 0) 914 diag("negative size (datsize = %lld, s->size = %lld)", datsize, s->size); 915 if(datsize + s->size < datsize) 916 diag("symbol too large (datsize = %lld, s->size = %lld)", datsize, s->size); 917 *datsizep = datsize + s->size; 918 } 919 920 void 921 dodata(void) 922 { 923 int32 n; 924 vlong datsize; 925 Section *sect; 926 Segment *segro; 927 LSym *s, *last, **l, *toc; 928 LSym *gcdata, *gcbss; 929 ProgGen gen; 930 931 if(debug['v']) 932 Bprint(&bso, "%5.2f dodata\n", cputime()); 933 Bflush(&bso); 934 935 last = nil; 936 datap = nil; 937 938 for(s=ctxt->allsym; s!=S; s=s->allsym) { 939 if(!s->reachable || s->special) 940 continue; 941 if(STEXT < s->type && s->type < SXREF) { 942 if(s->onlist) 943 sysfatal("symbol %s listed multiple times", s->name); 944 s->onlist = 1; 945 if(last == nil) 946 datap = s; 947 else 948 last->next = s; 949 s->next = nil; 950 last = s; 951 } 952 } 953 954 for(s = datap; s != nil; s = s->next) { 955 if(s->np > s->size) 956 diag("%s: initialize bounds (%lld < %d)", 957 s->name, (vlong)s->size, s->np); 958 } 959 960 961 /* 962 * now that we have the datap list, but before we start 963 * to assign addresses, record all the necessary 964 * dynamic relocations. these will grow the relocation 965 * symbol, which is itself data. 966 * 967 * on darwin, we need the symbol table numbers for dynreloc. 968 */ 969 if(HEADTYPE == Hdarwin) 970 machosymorder(); 971 dynreloc(); 972 973 /* some symbols may no longer belong in datap (Mach-O) */ 974 for(l=&datap; (s=*l) != nil; ) { 975 if(s->type <= STEXT || SXREF <= s->type) 976 *l = s->next; 977 else 978 l = &s->next; 979 } 980 *l = nil; 981 982 datap = listsort(datap, datcmp, offsetof(LSym, next)); 983 984 /* 985 * allocate sections. list is sorted by type, 986 * so we can just walk it for each piece we want to emit. 987 * segdata is processed before segtext, because we need 988 * to see all symbols in the .data and .bss sections in order 989 * to generate garbage collection information. 990 */ 991 992 /* begin segdata */ 993 994 /* skip symbols belonging to segtext */ 995 s = datap; 996 for(; s != nil && s->type < SELFSECT; s = s->next) 997 ; 998 999 /* writable ELF sections */ 1000 datsize = 0; 1001 for(; s != nil && s->type < SELFGOT; s = s->next) { 1002 sect = addsection(&segdata, s->name, 06); 1003 sect->align = symalign(s); 1004 datsize = rnd(datsize, sect->align); 1005 sect->vaddr = datsize; 1006 s->sect = sect; 1007 s->type = SDATA; 1008 s->value = datsize - sect->vaddr; 1009 growdatsize(&datsize, s); 1010 sect->len = datsize - sect->vaddr; 1011 } 1012 1013 /* .got (and .toc on ppc64) */ 1014 if(s->type == SELFGOT) { 1015 sect = addsection(&segdata, ".got", 06); 1016 sect->align = maxalign(s, SELFGOT); 1017 datsize = rnd(datsize, sect->align); 1018 sect->vaddr = datsize; 1019 for(; s != nil && s->type == SELFGOT; s = s->next) { 1020 datsize = aligndatsize(datsize, s); 1021 s->sect = sect; 1022 s->type = SDATA; 1023 s->value = datsize - sect->vaddr; 1024 1025 // Resolve .TOC. symbol for this object file (ppc64) 1026 toc = linkrlookup(ctxt, ".TOC.", s->version); 1027 if(toc != nil) { 1028 toc->sect = sect; 1029 toc->outer = s; 1030 toc->sub = s->sub; 1031 s->sub = toc; 1032 1033 toc->value = 0x8000; 1034 } 1035 growdatsize(&datsize, s); 1036 } 1037 sect->len = datsize - sect->vaddr; 1038 } 1039 1040 /* pointer-free data */ 1041 sect = addsection(&segdata, ".noptrdata", 06); 1042 sect->align = maxalign(s, SINITARR-1); 1043 datsize = rnd(datsize, sect->align); 1044 sect->vaddr = datsize; 1045 linklookup(ctxt, "runtime.noptrdata", 0)->sect = sect; 1046 linklookup(ctxt, "runtime.enoptrdata", 0)->sect = sect; 1047 for(; s != nil && s->type < SINITARR; s = s->next) { 1048 datsize = aligndatsize(datsize, s); 1049 s->sect = sect; 1050 s->type = SDATA; 1051 s->value = datsize - sect->vaddr; 1052 growdatsize(&datsize, s); 1053 } 1054 sect->len = datsize - sect->vaddr; 1055 1056 /* shared library initializer */ 1057 if(flag_shared) { 1058 sect = addsection(&segdata, ".init_array", 06); 1059 sect->align = maxalign(s, SINITARR); 1060 datsize = rnd(datsize, sect->align); 1061 sect->vaddr = datsize; 1062 for(; s != nil && s->type == SINITARR; s = s->next) { 1063 datsize = aligndatsize(datsize, s); 1064 s->sect = sect; 1065 s->value = datsize - sect->vaddr; 1066 growdatsize(&datsize, s); 1067 } 1068 sect->len = datsize - sect->vaddr; 1069 } 1070 1071 /* data */ 1072 sect = addsection(&segdata, ".data", 06); 1073 sect->align = maxalign(s, SBSS-1); 1074 datsize = rnd(datsize, sect->align); 1075 sect->vaddr = datsize; 1076 linklookup(ctxt, "runtime.data", 0)->sect = sect; 1077 linklookup(ctxt, "runtime.edata", 0)->sect = sect; 1078 gcdata = linklookup(ctxt, "runtime.gcdata", 0); 1079 proggeninit(&gen, gcdata); 1080 for(; s != nil && s->type < SBSS; s = s->next) { 1081 if(s->type == SINITARR) { 1082 ctxt->cursym = s; 1083 diag("unexpected symbol type %d", s->type); 1084 } 1085 s->sect = sect; 1086 s->type = SDATA; 1087 datsize = aligndatsize(datsize, s); 1088 s->value = datsize - sect->vaddr; 1089 proggenaddsym(&gen, s); // gc 1090 growdatsize(&datsize, s); 1091 } 1092 sect->len = datsize - sect->vaddr; 1093 proggenfini(&gen, sect->len); // gc 1094 1095 /* bss */ 1096 sect = addsection(&segdata, ".bss", 06); 1097 sect->align = maxalign(s, SNOPTRBSS-1); 1098 datsize = rnd(datsize, sect->align); 1099 sect->vaddr = datsize; 1100 linklookup(ctxt, "runtime.bss", 0)->sect = sect; 1101 linklookup(ctxt, "runtime.ebss", 0)->sect = sect; 1102 gcbss = linklookup(ctxt, "runtime.gcbss", 0); 1103 proggeninit(&gen, gcbss); 1104 for(; s != nil && s->type < SNOPTRBSS; s = s->next) { 1105 s->sect = sect; 1106 datsize = aligndatsize(datsize, s); 1107 s->value = datsize - sect->vaddr; 1108 proggenaddsym(&gen, s); // gc 1109 growdatsize(&datsize, s); 1110 } 1111 sect->len = datsize - sect->vaddr; 1112 proggenfini(&gen, sect->len); // gc 1113 1114 /* pointer-free bss */ 1115 sect = addsection(&segdata, ".noptrbss", 06); 1116 sect->align = maxalign(s, SNOPTRBSS); 1117 datsize = rnd(datsize, sect->align); 1118 sect->vaddr = datsize; 1119 linklookup(ctxt, "runtime.noptrbss", 0)->sect = sect; 1120 linklookup(ctxt, "runtime.enoptrbss", 0)->sect = sect; 1121 for(; s != nil && s->type == SNOPTRBSS; s = s->next) { 1122 datsize = aligndatsize(datsize, s); 1123 s->sect = sect; 1124 s->value = datsize - sect->vaddr; 1125 growdatsize(&datsize, s); 1126 } 1127 sect->len = datsize - sect->vaddr; 1128 linklookup(ctxt, "runtime.end", 0)->sect = sect; 1129 1130 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1131 if(datsize != (uint32)datsize) { 1132 diag("data or bss segment too large"); 1133 } 1134 1135 if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) { 1136 sect = addsection(&segdata, ".tbss", 06); 1137 sect->align = PtrSize; 1138 sect->vaddr = 0; 1139 datsize = 0; 1140 for(; s != nil && s->type == STLSBSS; s = s->next) { 1141 datsize = aligndatsize(datsize, s); 1142 s->sect = sect; 1143 s->value = datsize - sect->vaddr; 1144 growdatsize(&datsize, s); 1145 } 1146 sect->len = datsize; 1147 } else { 1148 // Might be internal linking but still using cgo. 1149 // In that case, the only possible STLSBSS symbol is runtime.tlsg. 1150 // Give it offset 0, because it's the only thing here. 1151 if(s != nil && s->type == STLSBSS && strcmp(s->name, "runtime.tlsg") == 0) { 1152 s->value = 0; 1153 s = s->next; 1154 } 1155 } 1156 1157 if(s != nil) { 1158 ctxt->cursym = nil; 1159 diag("unexpected symbol type %d for %s", s->type, s->name); 1160 } 1161 1162 /* 1163 * We finished data, begin read-only data. 1164 * Not all systems support a separate read-only non-executable data section. 1165 * ELF systems do. 1166 * OS X and Plan 9 do not. 1167 * Windows PE may, but if so we have not implemented it. 1168 * And if we're using external linking mode, the point is moot, 1169 * since it's not our decision; that code expects the sections in 1170 * segtext. 1171 */ 1172 if(iself && linkmode == LinkInternal) 1173 segro = &segrodata; 1174 else 1175 segro = &segtext; 1176 1177 s = datap; 1178 1179 datsize = 0; 1180 1181 /* read-only executable ELF, Mach-O sections */ 1182 for(; s != nil && s->type < STYPE; s = s->next) { 1183 sect = addsection(&segtext, s->name, 04); 1184 sect->align = symalign(s); 1185 datsize = rnd(datsize, sect->align); 1186 sect->vaddr = datsize; 1187 s->sect = sect; 1188 s->type = SRODATA; 1189 s->value = datsize - sect->vaddr; 1190 growdatsize(&datsize, s); 1191 sect->len = datsize - sect->vaddr; 1192 } 1193 1194 /* read-only data */ 1195 sect = addsection(segro, ".rodata", 04); 1196 sect->align = maxalign(s, STYPELINK-1); 1197 datsize = rnd(datsize, sect->align); 1198 sect->vaddr = 0; 1199 linklookup(ctxt, "runtime.rodata", 0)->sect = sect; 1200 linklookup(ctxt, "runtime.erodata", 0)->sect = sect; 1201 for(; s != nil && s->type < STYPELINK; s = s->next) { 1202 datsize = aligndatsize(datsize, s); 1203 s->sect = sect; 1204 s->type = SRODATA; 1205 s->value = datsize - sect->vaddr; 1206 growdatsize(&datsize, s); 1207 } 1208 sect->len = datsize - sect->vaddr; 1209 1210 /* typelink */ 1211 sect = addsection(segro, ".typelink", 04); 1212 sect->align = maxalign(s, STYPELINK); 1213 datsize = rnd(datsize, sect->align); 1214 sect->vaddr = datsize; 1215 linklookup(ctxt, "runtime.typelink", 0)->sect = sect; 1216 linklookup(ctxt, "runtime.etypelink", 0)->sect = sect; 1217 for(; s != nil && s->type == STYPELINK; s = s->next) { 1218 datsize = aligndatsize(datsize, s); 1219 s->sect = sect; 1220 s->type = SRODATA; 1221 s->value = datsize - sect->vaddr; 1222 growdatsize(&datsize, s); 1223 } 1224 sect->len = datsize - sect->vaddr; 1225 1226 /* gosymtab */ 1227 sect = addsection(segro, ".gosymtab", 04); 1228 sect->align = maxalign(s, SPCLNTAB-1); 1229 datsize = rnd(datsize, sect->align); 1230 sect->vaddr = datsize; 1231 linklookup(ctxt, "runtime.symtab", 0)->sect = sect; 1232 linklookup(ctxt, "runtime.esymtab", 0)->sect = sect; 1233 for(; s != nil && s->type < SPCLNTAB; s = s->next) { 1234 datsize = aligndatsize(datsize, s); 1235 s->sect = sect; 1236 s->type = SRODATA; 1237 s->value = datsize - sect->vaddr; 1238 growdatsize(&datsize, s); 1239 } 1240 sect->len = datsize - sect->vaddr; 1241 1242 /* gopclntab */ 1243 sect = addsection(segro, ".gopclntab", 04); 1244 sect->align = maxalign(s, SELFROSECT-1); 1245 datsize = rnd(datsize, sect->align); 1246 sect->vaddr = datsize; 1247 linklookup(ctxt, "runtime.pclntab", 0)->sect = sect; 1248 linklookup(ctxt, "runtime.epclntab", 0)->sect = sect; 1249 for(; s != nil && s->type < SELFROSECT; s = s->next) { 1250 datsize = aligndatsize(datsize, s); 1251 s->sect = sect; 1252 s->type = SRODATA; 1253 s->value = datsize - sect->vaddr; 1254 growdatsize(&datsize, s); 1255 } 1256 sect->len = datsize - sect->vaddr; 1257 1258 /* read-only ELF, Mach-O sections */ 1259 for(; s != nil && s->type < SELFSECT; s = s->next) { 1260 sect = addsection(segro, s->name, 04); 1261 sect->align = symalign(s); 1262 datsize = rnd(datsize, sect->align); 1263 sect->vaddr = datsize; 1264 s->sect = sect; 1265 s->type = SRODATA; 1266 s->value = datsize - sect->vaddr; 1267 growdatsize(&datsize, s); 1268 sect->len = datsize - sect->vaddr; 1269 } 1270 1271 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1272 if(datsize != (uint32)datsize) { 1273 diag("read-only data segment too large"); 1274 } 1275 1276 /* number the sections */ 1277 n = 1; 1278 for(sect = segtext.sect; sect != nil; sect = sect->next) 1279 sect->extnum = n++; 1280 for(sect = segrodata.sect; sect != nil; sect = sect->next) 1281 sect->extnum = n++; 1282 for(sect = segdata.sect; sect != nil; sect = sect->next) 1283 sect->extnum = n++; 1284 } 1285 1286 // assign addresses to text 1287 void 1288 textaddress(void) 1289 { 1290 uvlong va; 1291 Section *sect; 1292 LSym *sym, *sub; 1293 1294 addsection(&segtext, ".text", 05); 1295 1296 // Assign PCs in text segment. 1297 // Could parallelize, by assigning to text 1298 // and then letting threads copy down, but probably not worth it. 1299 sect = segtext.sect; 1300 sect->align = funcalign; 1301 linklookup(ctxt, "runtime.text", 0)->sect = sect; 1302 linklookup(ctxt, "runtime.etext", 0)->sect = sect; 1303 va = INITTEXT; 1304 sect->vaddr = va; 1305 for(sym = ctxt->textp; sym != nil; sym = sym->next) { 1306 sym->sect = sect; 1307 if(sym->type & SSUB) 1308 continue; 1309 if(sym->align != 0) 1310 va = rnd(va, sym->align); 1311 else 1312 va = rnd(va, funcalign); 1313 sym->value = 0; 1314 for(sub = sym; sub != S; sub = sub->sub) 1315 sub->value += va; 1316 if(sym->size == 0 && sym->sub != S) 1317 ctxt->cursym = sym; 1318 if(sym->size < MINFUNC) 1319 va += MINFUNC; // spacing required for findfunctab 1320 else 1321 va += sym->size; 1322 } 1323 sect->len = va - sect->vaddr; 1324 } 1325 1326 // assign addresses 1327 void 1328 address(void) 1329 { 1330 Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss; 1331 Section *typelink; 1332 LSym *sym, *sub; 1333 uvlong va; 1334 vlong vlen; 1335 1336 va = INITTEXT; 1337 segtext.rwx = 05; 1338 segtext.vaddr = va; 1339 segtext.fileoff = HEADR; 1340 for(s=segtext.sect; s != nil; s=s->next) { 1341 va = rnd(va, s->align); 1342 s->vaddr = va; 1343 va += s->len; 1344 } 1345 segtext.len = va - INITTEXT; 1346 segtext.filelen = segtext.len; 1347 if(HEADTYPE == Hnacl) 1348 va += 32; // room for the "halt sled" 1349 1350 if(segrodata.sect != nil) { 1351 // align to page boundary so as not to mix 1352 // rodata and executable text. 1353 va = rnd(va, INITRND); 1354 1355 segrodata.rwx = 04; 1356 segrodata.vaddr = va; 1357 segrodata.fileoff = va - segtext.vaddr + segtext.fileoff; 1358 segrodata.filelen = 0; 1359 for(s=segrodata.sect; s != nil; s=s->next) { 1360 va = rnd(va, s->align); 1361 s->vaddr = va; 1362 va += s->len; 1363 } 1364 segrodata.len = va - segrodata.vaddr; 1365 segrodata.filelen = segrodata.len; 1366 } 1367 1368 va = rnd(va, INITRND); 1369 segdata.rwx = 06; 1370 segdata.vaddr = va; 1371 segdata.fileoff = va - segtext.vaddr + segtext.fileoff; 1372 segdata.filelen = 0; 1373 if(HEADTYPE == Hwindows) 1374 segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN); 1375 if(HEADTYPE == Hplan9) 1376 segdata.fileoff = segtext.fileoff + segtext.filelen; 1377 data = nil; 1378 noptr = nil; 1379 bss = nil; 1380 noptrbss = nil; 1381 for(s=segdata.sect; s != nil; s=s->next) { 1382 vlen = s->len; 1383 if(s->next) 1384 vlen = s->next->vaddr - s->vaddr; 1385 s->vaddr = va; 1386 va += vlen; 1387 segdata.len = va - segdata.vaddr; 1388 if(strcmp(s->name, ".data") == 0) 1389 data = s; 1390 if(strcmp(s->name, ".noptrdata") == 0) 1391 noptr = s; 1392 if(strcmp(s->name, ".bss") == 0) 1393 bss = s; 1394 if(strcmp(s->name, ".noptrbss") == 0) 1395 noptrbss = s; 1396 } 1397 segdata.filelen = bss->vaddr - segdata.vaddr; 1398 1399 text = segtext.sect; 1400 if(segrodata.sect) 1401 rodata = segrodata.sect; 1402 else 1403 rodata = text->next; 1404 typelink = rodata->next; 1405 symtab = typelink->next; 1406 pclntab = symtab->next; 1407 1408 for(sym = datap; sym != nil; sym = sym->next) { 1409 ctxt->cursym = sym; 1410 if(sym->sect != nil) 1411 sym->value += sym->sect->vaddr; 1412 for(sub = sym->sub; sub != nil; sub = sub->sub) 1413 sub->value += sym->value; 1414 } 1415 1416 xdefine("runtime.text", STEXT, text->vaddr); 1417 xdefine("runtime.etext", STEXT, text->vaddr + text->len); 1418 xdefine("runtime.rodata", SRODATA, rodata->vaddr); 1419 xdefine("runtime.erodata", SRODATA, rodata->vaddr + rodata->len); 1420 xdefine("runtime.typelink", SRODATA, typelink->vaddr); 1421 xdefine("runtime.etypelink", SRODATA, typelink->vaddr + typelink->len); 1422 1423 sym = linklookup(ctxt, "runtime.gcdata", 0); 1424 xdefine("runtime.egcdata", SRODATA, symaddr(sym) + sym->size); 1425 linklookup(ctxt, "runtime.egcdata", 0)->sect = sym->sect; 1426 1427 sym = linklookup(ctxt, "runtime.gcbss", 0); 1428 xdefine("runtime.egcbss", SRODATA, symaddr(sym) + sym->size); 1429 linklookup(ctxt, "runtime.egcbss", 0)->sect = sym->sect; 1430 1431 xdefine("runtime.symtab", SRODATA, symtab->vaddr); 1432 xdefine("runtime.esymtab", SRODATA, symtab->vaddr + symtab->len); 1433 xdefine("runtime.pclntab", SRODATA, pclntab->vaddr); 1434 xdefine("runtime.epclntab", SRODATA, pclntab->vaddr + pclntab->len); 1435 xdefine("runtime.noptrdata", SNOPTRDATA, noptr->vaddr); 1436 xdefine("runtime.enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len); 1437 xdefine("runtime.bss", SBSS, bss->vaddr); 1438 xdefine("runtime.ebss", SBSS, bss->vaddr + bss->len); 1439 xdefine("runtime.data", SDATA, data->vaddr); 1440 xdefine("runtime.edata", SDATA, data->vaddr + data->len); 1441 xdefine("runtime.noptrbss", SNOPTRBSS, noptrbss->vaddr); 1442 xdefine("runtime.enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len); 1443 xdefine("runtime.end", SBSS, segdata.vaddr + segdata.len); 1444 }