github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/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 "../../pkg/runtime/mgc0.h" 39 40 void dynreloc(void); 41 static vlong addaddrplus4(Sym *s, Sym *t, vlong add); 42 43 /* 44 * divide-and-conquer list-link 45 * sort of Sym* structures. 46 * Used for the data block. 47 */ 48 int 49 datcmp(Sym *s1, Sym *s2) 50 { 51 if(s1->type != s2->type) 52 return (int)s1->type - (int)s2->type; 53 if(s1->size != s2->size) { 54 if(s1->size < s2->size) 55 return -1; 56 return +1; 57 } 58 return strcmp(s1->name, s2->name); 59 } 60 61 Sym* 62 listsort(Sym *l, int (*cmp)(Sym*, Sym*), int off) 63 { 64 Sym *l1, *l2, *le; 65 #define NEXT(l) (*(Sym**)((char*)(l)+off)) 66 67 if(l == 0 || NEXT(l) == 0) 68 return l; 69 70 l1 = l; 71 l2 = l; 72 for(;;) { 73 l2 = NEXT(l2); 74 if(l2 == 0) 75 break; 76 l2 = NEXT(l2); 77 if(l2 == 0) 78 break; 79 l1 = NEXT(l1); 80 } 81 82 l2 = NEXT(l1); 83 NEXT(l1) = 0; 84 l1 = listsort(l, cmp, off); 85 l2 = listsort(l2, cmp, off); 86 87 /* set up lead element */ 88 if(cmp(l1, l2) < 0) { 89 l = l1; 90 l1 = NEXT(l1); 91 } else { 92 l = l2; 93 l2 = NEXT(l2); 94 } 95 le = l; 96 97 for(;;) { 98 if(l1 == 0) { 99 while(l2) { 100 NEXT(le) = l2; 101 le = l2; 102 l2 = NEXT(l2); 103 } 104 NEXT(le) = 0; 105 break; 106 } 107 if(l2 == 0) { 108 while(l1) { 109 NEXT(le) = l1; 110 le = l1; 111 l1 = NEXT(l1); 112 } 113 break; 114 } 115 if(cmp(l1, l2) < 0) { 116 NEXT(le) = l1; 117 le = l1; 118 l1 = NEXT(l1); 119 } else { 120 NEXT(le) = l2; 121 le = l2; 122 l2 = NEXT(l2); 123 } 124 } 125 NEXT(le) = 0; 126 return l; 127 128 #undef NEXT 129 } 130 131 Reloc* 132 addrel(Sym *s) 133 { 134 if(s->nr >= s->maxr) { 135 if(s->maxr == 0) 136 s->maxr = 4; 137 else 138 s->maxr <<= 1; 139 s->r = erealloc(s->r, s->maxr*sizeof s->r[0]); 140 memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]); 141 } 142 return &s->r[s->nr++]; 143 } 144 145 void 146 relocsym(Sym *s) 147 { 148 Reloc *r; 149 Sym *rs; 150 Prog p; 151 int32 i, off, siz, fl; 152 vlong o; 153 uchar *cast; 154 155 cursym = s; 156 memset(&p, 0, sizeof p); 157 for(r=s->r; r<s->r+s->nr; r++) { 158 r->done = 1; 159 off = r->off; 160 siz = r->siz; 161 if(off < 0 || off+siz > s->np) { 162 diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np); 163 continue; 164 } 165 if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) { 166 diag("%s: not defined", r->sym->name); 167 continue; 168 } 169 if(r->type >= 256) 170 continue; 171 172 if(r->sym != S && r->sym->type == SDYNIMPORT) 173 diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type); 174 175 if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable) 176 diag("unreachable sym in relocation: %s %s", s->name, r->sym->name); 177 178 switch(r->type) { 179 default: 180 o = 0; 181 if(archreloc(r, s, &o) < 0) 182 diag("unknown reloc %d", r->type); 183 break; 184 case D_TLS: 185 r->done = 0; 186 o = 0; 187 if(thechar != '6') 188 o = r->add; 189 break; 190 case D_ADDR: 191 if(linkmode == LinkExternal && r->sym->type != SCONST) { 192 r->done = 0; 193 194 // set up addend for eventual relocation via outer symbol. 195 rs = r->sym; 196 r->xadd = r->add; 197 while(rs->outer != nil) { 198 r->xadd += symaddr(rs) - symaddr(rs->outer); 199 rs = rs->outer; 200 } 201 if(rs->type != SHOSTOBJ && rs->sect == nil) 202 diag("missing section for %s", rs->name); 203 r->xsym = rs; 204 205 o = r->xadd; 206 if(iself) { 207 if(thechar == '6') 208 o = 0; 209 } else if(HEADTYPE == Hdarwin) { 210 if(rs->type != SHOSTOBJ) 211 o += symaddr(rs); 212 } else { 213 diag("unhandled pcrel relocation for %s", headtype); 214 } 215 break; 216 } 217 o = symaddr(r->sym) + r->add; 218 break; 219 case D_PCREL: 220 // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. 221 if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) { 222 r->done = 0; 223 224 // set up addend for eventual relocation via outer symbol. 225 rs = r->sym; 226 r->xadd = r->add; 227 while(rs->outer != nil) { 228 r->xadd += symaddr(rs) - symaddr(rs->outer); 229 rs = rs->outer; 230 } 231 r->xadd -= r->siz; // relative to address after the relocated chunk 232 if(rs->type != SHOSTOBJ && rs->sect == nil) 233 diag("missing section for %s", rs->name); 234 r->xsym = rs; 235 236 o = r->xadd; 237 if(iself) { 238 if(thechar == '6') 239 o = 0; 240 } else if(HEADTYPE == Hdarwin) { 241 if(rs->type != SHOSTOBJ) 242 o += symaddr(rs) - rs->sect->vaddr; 243 o -= r->off; // WTF? 244 } else { 245 diag("unhandled pcrel relocation for %s", headtype); 246 } 247 break; 248 } 249 o = 0; 250 if(r->sym) 251 o += symaddr(r->sym); 252 // NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c 253 // compiler. The expression s->value + r->off + r->siz is int32 + int32 + 254 // uchar, and Plan 9 8c incorrectly treats the expression as type uint32 255 // instead of int32, causing incorrect values when sign extended for adding 256 // to o. The bug only occurs on Plan 9, because this C program is compiled by 257 // the standard host compiler (gcc on most other systems). 258 o += r->add - (s->value + r->off + (int32)r->siz); 259 break; 260 case D_SIZE: 261 o = r->sym->size + r->add; 262 break; 263 } 264 //print("relocate %s %p %s => %p %p %p %p [%p]\n", s->name, s->value+off, r->sym ? r->sym->name : "<nil>", (void*)symaddr(r->sym), (void*)s->value, (void*)r->off, (void*)r->siz, (void*)o); 265 switch(siz) { 266 default: 267 cursym = s; 268 diag("bad reloc size %#ux for %s", siz, r->sym->name); 269 case 4: 270 if(r->type == D_PCREL) { 271 if(o != (int32)o) 272 diag("pc-relative relocation address is too big: %#llx", o); 273 } else { 274 if(o != (int32)o && o != (uint32)o) 275 diag("non-pc-relative relocation address is too big: %#llux", o); 276 } 277 fl = o; 278 cast = (uchar*)&fl; 279 for(i=0; i<4; i++) 280 s->p[off+i] = cast[inuxi4[i]]; 281 break; 282 case 8: 283 cast = (uchar*)&o; 284 for(i=0; i<8; i++) 285 s->p[off+i] = cast[inuxi8[i]]; 286 break; 287 } 288 } 289 } 290 291 void 292 reloc(void) 293 { 294 Sym *s; 295 296 if(debug['v']) 297 Bprint(&bso, "%5.2f reloc\n", cputime()); 298 Bflush(&bso); 299 300 for(s=textp; s!=S; s=s->next) 301 relocsym(s); 302 for(s=datap; s!=S; s=s->next) 303 relocsym(s); 304 } 305 306 void 307 dynrelocsym(Sym *s) 308 { 309 Reloc *r; 310 311 if(HEADTYPE == Hwindows) { 312 Sym *rel, *targ; 313 314 rel = lookup(".rel", 0); 315 if(s == rel) 316 return; 317 for(r=s->r; r<s->r+s->nr; r++) { 318 targ = r->sym; 319 if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. 320 targ->plt = rel->size; 321 r->sym = rel; 322 r->add = targ->plt; 323 324 // jmp *addr 325 if(thechar == '8') { 326 adduint8(rel, 0xff); 327 adduint8(rel, 0x25); 328 addaddr(rel, targ); 329 adduint8(rel, 0x90); 330 adduint8(rel, 0x90); 331 } else { 332 adduint8(rel, 0xff); 333 adduint8(rel, 0x24); 334 adduint8(rel, 0x25); 335 addaddrplus4(rel, targ, 0); 336 adduint8(rel, 0x90); 337 } 338 } else if(r->sym->plt >= 0) { 339 r->sym = rel; 340 r->add = targ->plt; 341 } 342 } 343 return; 344 } 345 346 for(r=s->r; r<s->r+s->nr; r++) { 347 if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) 348 adddynrel(s, r); 349 } 350 } 351 352 void 353 dynreloc(void) 354 { 355 Sym *s; 356 357 // -d suppresses dynamic loader format, so we may as well not 358 // compute these sections or mark their symbols as reachable. 359 if(debug['d'] && HEADTYPE != Hwindows) 360 return; 361 if(debug['v']) 362 Bprint(&bso, "%5.2f reloc\n", cputime()); 363 Bflush(&bso); 364 365 for(s=textp; s!=S; s=s->next) 366 dynrelocsym(s); 367 for(s=datap; s!=S; s=s->next) 368 dynrelocsym(s); 369 if(iself) 370 elfdynhash(); 371 } 372 373 void 374 symgrow(Sym *s, int32 siz) 375 { 376 if(s->np >= siz) 377 return; 378 379 if(s->maxp < siz) { 380 if(s->maxp == 0) 381 s->maxp = 8; 382 while(s->maxp < siz) 383 s->maxp <<= 1; 384 s->p = erealloc(s->p, s->maxp); 385 memset(s->p+s->np, 0, s->maxp-s->np); 386 } 387 s->np = siz; 388 } 389 390 void 391 savedata(Sym *s, Prog *p, char *pn) 392 { 393 int32 off, siz, i, fl; 394 uchar *cast; 395 vlong o; 396 Reloc *r; 397 398 off = p->from.offset; 399 siz = p->datasize; 400 if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100) 401 mangle(pn); 402 symgrow(s, off+siz); 403 404 switch(p->to.type) { 405 default: 406 diag("bad data: %P", p); 407 break; 408 409 case D_FCONST: 410 switch(siz) { 411 default: 412 case 4: 413 fl = ieeedtof(&p->to.ieee); 414 cast = (uchar*)&fl; 415 for(i=0; i<4; i++) 416 s->p[off+i] = cast[fnuxi4[i]]; 417 break; 418 case 8: 419 cast = (uchar*)&p->to.ieee; 420 for(i=0; i<8; i++) 421 s->p[off+i] = cast[fnuxi8[i]]; 422 break; 423 } 424 break; 425 426 case D_SCONST: 427 for(i=0; i<siz; i++) 428 s->p[off+i] = p->to.scon[i]; 429 break; 430 431 case D_CONST: 432 if(p->to.sym) 433 goto Addr; 434 o = p->to.offset; 435 fl = o; 436 cast = (uchar*)&fl; 437 switch(siz) { 438 default: 439 diag("bad nuxi %d\n%P", siz, p); 440 break; 441 case 1: 442 s->p[off] = cast[inuxi1[0]]; 443 break; 444 case 2: 445 for(i=0; i<2; i++) 446 s->p[off+i] = cast[inuxi2[i]]; 447 break; 448 case 4: 449 for(i=0; i<4; i++) 450 s->p[off+i] = cast[inuxi4[i]]; 451 break; 452 case 8: 453 cast = (uchar*)&o; 454 for(i=0; i<8; i++) 455 s->p[off+i] = cast[inuxi8[i]]; 456 break; 457 } 458 break; 459 460 case D_ADDR: 461 case D_SIZE: 462 Addr: 463 r = addrel(s); 464 r->off = off; 465 r->siz = siz; 466 r->sym = p->to.sym; 467 r->type = p->to.type; 468 if(r->type != D_SIZE) 469 r->type = D_ADDR; 470 r->add = p->to.offset; 471 break; 472 } 473 } 474 475 static void 476 blk(Sym *start, int32 addr, int32 size) 477 { 478 Sym *sym; 479 int32 eaddr; 480 uchar *p, *ep; 481 482 for(sym = start; sym != nil; sym = sym->next) 483 if(!(sym->type&SSUB) && sym->value >= addr) 484 break; 485 486 eaddr = addr+size; 487 for(; sym != nil; sym = sym->next) { 488 if(sym->type&SSUB) 489 continue; 490 if(sym->value >= eaddr) 491 break; 492 if(sym->value < addr) { 493 diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type); 494 errorexit(); 495 } 496 cursym = sym; 497 for(; addr < sym->value; addr++) 498 cput(0); 499 p = sym->p; 500 ep = p + sym->np; 501 while(p < ep) 502 cput(*p++); 503 addr += sym->np; 504 for(; addr < sym->value+sym->size; addr++) 505 cput(0); 506 if(addr != sym->value+sym->size) { 507 diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size); 508 errorexit(); 509 } 510 } 511 512 for(; addr < eaddr; addr++) 513 cput(0); 514 cflush(); 515 } 516 517 void 518 codeblk(int32 addr, int32 size) 519 { 520 Sym *sym; 521 int32 eaddr, n, epc; 522 Prog *p; 523 uchar *q; 524 525 if(debug['a']) 526 Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos()); 527 528 blk(textp, addr, size); 529 530 /* again for printing */ 531 if(!debug['a']) 532 return; 533 534 for(sym = textp; sym != nil; sym = sym->next) { 535 if(!sym->reachable) 536 continue; 537 if(sym->value >= addr) 538 break; 539 } 540 541 eaddr = addr + size; 542 for(; sym != nil; sym = sym->next) { 543 if(!sym->reachable) 544 continue; 545 if(sym->value >= eaddr) 546 break; 547 548 if(addr < sym->value) { 549 Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr); 550 for(; addr < sym->value; addr++) 551 Bprint(&bso, " %.2ux", 0); 552 Bprint(&bso, "\n"); 553 } 554 p = sym->text; 555 if(p == nil) { 556 Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name); 557 n = sym->size; 558 q = sym->p; 559 560 while(n >= 16) { 561 Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q); 562 addr += 16; 563 q += 16; 564 n -= 16; 565 } 566 if(n > 0) 567 Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q); 568 addr += n; 569 continue; 570 } 571 572 Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p); 573 for(p = p->link; p != P; p = p->link) { 574 if(p->link != P) 575 epc = p->link->pc; 576 else 577 epc = sym->value + sym->size; 578 Bprint(&bso, "%.6llux\t", (uvlong)p->pc); 579 q = sym->p + p->pc - sym->value; 580 n = epc - p->pc; 581 Bprint(&bso, "%-20.*I | %P\n", (int)n, q, p); 582 addr += n; 583 } 584 } 585 586 if(addr < eaddr) { 587 Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr); 588 for(; addr < eaddr; addr++) 589 Bprint(&bso, " %.2ux", 0); 590 } 591 Bflush(&bso); 592 } 593 594 void 595 datblk(int32 addr, int32 size) 596 { 597 Sym *sym; 598 int32 i, eaddr; 599 uchar *p, *ep; 600 char *typ, *rsname; 601 Reloc *r; 602 603 if(debug['a']) 604 Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos()); 605 606 blk(datap, addr, size); 607 608 /* again for printing */ 609 if(!debug['a']) 610 return; 611 612 for(sym = datap; sym != nil; sym = sym->next) 613 if(sym->value >= addr) 614 break; 615 616 eaddr = addr + size; 617 for(; sym != nil; sym = sym->next) { 618 if(sym->value >= eaddr) 619 break; 620 if(addr < sym->value) { 621 Bprint(&bso, "\t%.8ux| 00 ...\n", addr); 622 addr = sym->value; 623 } 624 Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr); 625 p = sym->p; 626 ep = p + sym->np; 627 while(p < ep) { 628 if(p > sym->p && (int)(p-sym->p)%16 == 0) 629 Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p))); 630 Bprint(&bso, " %.2ux", *p++); 631 } 632 addr += sym->np; 633 for(; addr < sym->value+sym->size; addr++) 634 Bprint(&bso, " %.2ux", 0); 635 Bprint(&bso, "\n"); 636 637 if(linkmode == LinkExternal) { 638 for(i=0; i<sym->nr; i++) { 639 r = &sym->r[i]; 640 rsname = ""; 641 if(r->sym) 642 rsname = r->sym->name; 643 typ = "?"; 644 switch(r->type) { 645 case D_ADDR: 646 typ = "addr"; 647 break; 648 case D_PCREL: 649 typ = "pcrel"; 650 break; 651 } 652 Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n", 653 (uint)(sym->value+r->off), r->siz, typ, rsname, (vlong)r->add, (vlong)(r->sym->value+r->add)); 654 } 655 } 656 } 657 658 if(addr < eaddr) 659 Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr); 660 Bprint(&bso, "\t%.8ux|\n", (uint)eaddr); 661 } 662 663 void 664 strnput(char *s, int n) 665 { 666 for(; n > 0 && *s; s++) { 667 cput(*s); 668 n--; 669 } 670 while(n > 0) { 671 cput(0); 672 n--; 673 } 674 } 675 676 void 677 addstrdata(char *name, char *value) 678 { 679 Sym *s, *sp; 680 char *p; 681 682 p = smprint("%s.str", name); 683 sp = lookup(p, 0); 684 free(p); 685 addstring(sp, value); 686 687 s = lookup(name, 0); 688 s->size = 0; 689 s->dupok = 1; 690 addaddr(s, sp); 691 adduint32(s, strlen(value)); 692 if(PtrSize == 8) 693 adduint32(s, 0); // round struct to pointer width 694 695 // in case reachability has already been computed 696 sp->reachable = s->reachable; 697 } 698 699 vlong 700 addstring(Sym *s, char *str) 701 { 702 int n; 703 int32 r; 704 705 if(s->type == 0) 706 s->type = SNOPTRDATA; 707 s->reachable = 1; 708 r = s->size; 709 n = strlen(str)+1; 710 if(strcmp(s->name, ".shstrtab") == 0) 711 elfsetstring(str, r); 712 symgrow(s, r+n); 713 memmove(s->p+r, str, n); 714 s->size += n; 715 return r; 716 } 717 718 vlong 719 setuintxx(Sym *s, vlong off, uint64 v, vlong wid) 720 { 721 int32 i, fl; 722 vlong o; 723 uchar *cast; 724 725 if(s->type == 0) 726 s->type = SDATA; 727 s->reachable = 1; 728 if(s->size < off+wid) { 729 s->size = off+wid; 730 symgrow(s, s->size); 731 } 732 fl = v; 733 cast = (uchar*)&fl; 734 switch(wid) { 735 case 1: 736 s->p[off] = cast[inuxi1[0]]; 737 break; 738 case 2: 739 for(i=0; i<2; i++) 740 s->p[off+i] = cast[inuxi2[i]]; 741 break; 742 case 4: 743 for(i=0; i<4; i++) 744 s->p[off+i] = cast[inuxi4[i]]; 745 break; 746 case 8: 747 o = v; 748 cast = (uchar*)&o; 749 for(i=0; i<8; i++) 750 s->p[off+i] = cast[inuxi8[i]]; 751 break; 752 } 753 return off+wid; 754 } 755 756 vlong 757 adduintxx(Sym *s, uint64 v, int wid) 758 { 759 vlong off; 760 761 off = s->size; 762 setuintxx(s, off, v, wid); 763 return off; 764 } 765 766 vlong 767 adduint8(Sym *s, uint8 v) 768 { 769 return adduintxx(s, v, 1); 770 } 771 772 vlong 773 adduint16(Sym *s, uint16 v) 774 { 775 return adduintxx(s, v, 2); 776 } 777 778 vlong 779 adduint32(Sym *s, uint32 v) 780 { 781 return adduintxx(s, v, 4); 782 } 783 784 vlong 785 adduint64(Sym *s, uint64 v) 786 { 787 return adduintxx(s, v, 8); 788 } 789 790 vlong 791 setuint8(Sym *s, vlong r, uint8 v) 792 { 793 return setuintxx(s, r, v, 1); 794 } 795 796 vlong 797 setuint16(Sym *s, vlong r, uint16 v) 798 { 799 return setuintxx(s, r, v, 2); 800 } 801 802 vlong 803 setuint32(Sym *s, vlong r, uint32 v) 804 { 805 return setuintxx(s, r, v, 4); 806 } 807 808 vlong 809 setuint64(Sym *s, vlong r, uint64 v) 810 { 811 return setuintxx(s, r, v, 8); 812 } 813 814 vlong 815 addaddrplus(Sym *s, Sym *t, vlong add) 816 { 817 vlong i; 818 Reloc *r; 819 820 if(s->type == 0) 821 s->type = SDATA; 822 s->reachable = 1; 823 i = s->size; 824 s->size += PtrSize; 825 symgrow(s, s->size); 826 r = addrel(s); 827 r->sym = t; 828 r->off = i; 829 r->siz = PtrSize; 830 r->type = D_ADDR; 831 r->add = add; 832 return i + r->siz; 833 } 834 835 static vlong 836 addaddrplus4(Sym *s, Sym *t, vlong add) 837 { 838 vlong i; 839 Reloc *r; 840 841 if(s->type == 0) 842 s->type = SDATA; 843 s->reachable = 1; 844 i = s->size; 845 s->size += 4; 846 symgrow(s, s->size); 847 r = addrel(s); 848 r->sym = t; 849 r->off = i; 850 r->siz = 4; 851 r->type = D_ADDR; 852 r->add = add; 853 return i + r->siz; 854 } 855 856 vlong 857 addpcrelplus(Sym *s, Sym *t, vlong add) 858 { 859 vlong i; 860 Reloc *r; 861 862 if(s->type == 0) 863 s->type = SDATA; 864 s->reachable = 1; 865 i = s->size; 866 s->size += 4; 867 symgrow(s, s->size); 868 r = addrel(s); 869 r->sym = t; 870 r->off = i; 871 r->add = add; 872 r->type = D_PCREL; 873 r->siz = 4; 874 return i + r->siz; 875 } 876 877 vlong 878 addaddr(Sym *s, Sym *t) 879 { 880 return addaddrplus(s, t, 0); 881 } 882 883 vlong 884 setaddrplus(Sym *s, vlong off, Sym *t, vlong add) 885 { 886 Reloc *r; 887 888 if(s->type == 0) 889 s->type = SDATA; 890 s->reachable = 1; 891 if(off+PtrSize > s->size) { 892 s->size = off + PtrSize; 893 symgrow(s, s->size); 894 } 895 r = addrel(s); 896 r->sym = t; 897 r->off = off; 898 r->siz = PtrSize; 899 r->type = D_ADDR; 900 r->add = add; 901 return off + r->siz; 902 } 903 904 vlong 905 setaddr(Sym *s, vlong off, Sym *t) 906 { 907 return setaddrplus(s, off, t, 0); 908 } 909 910 vlong 911 addsize(Sym *s, Sym *t) 912 { 913 vlong i; 914 Reloc *r; 915 916 if(s->type == 0) 917 s->type = SDATA; 918 s->reachable = 1; 919 i = s->size; 920 s->size += PtrSize; 921 symgrow(s, s->size); 922 r = addrel(s); 923 r->sym = t; 924 r->off = i; 925 r->siz = PtrSize; 926 r->type = D_SIZE; 927 return i + r->siz; 928 } 929 930 void 931 dosymtype(void) 932 { 933 Sym *s; 934 935 for(s = allsym; s != nil; s = s->allsym) { 936 if(s->np > 0) { 937 if(s->type == SBSS) 938 s->type = SDATA; 939 if(s->type == SNOPTRBSS) 940 s->type = SNOPTRDATA; 941 } 942 } 943 } 944 945 static int32 946 symalign(Sym *s) 947 { 948 int32 align; 949 950 if(s->align != 0) 951 return s->align; 952 953 align = MaxAlign; 954 while(align > s->size && align > 1) 955 align >>= 1; 956 if(align < s->align) 957 align = s->align; 958 return align; 959 } 960 961 static vlong 962 aligndatsize(vlong datsize, Sym *s) 963 { 964 return rnd(datsize, symalign(s)); 965 } 966 967 // maxalign returns the maximum required alignment for 968 // the list of symbols s; the list stops when s->type exceeds type. 969 static int32 970 maxalign(Sym *s, int type) 971 { 972 int32 align, max; 973 974 max = 0; 975 for(; s != S && s->type <= type; s = s->next) { 976 align = symalign(s); 977 if(max < align) 978 max = align; 979 } 980 return max; 981 } 982 983 static void 984 gcaddsym(Sym *gc, Sym *s, vlong off) 985 { 986 vlong a; 987 Sym *gotype; 988 989 if(s->size < PtrSize) 990 return; 991 if(strcmp(s->name, ".string") == 0) 992 return; 993 994 gotype = s->gotype; 995 if(gotype != nil) { 996 //print("gcaddsym: %s %d %s\n", s->name, s->size, gotype->name); 997 adduintxx(gc, GC_CALL, PtrSize); 998 adduintxx(gc, off, PtrSize); 999 addpcrelplus(gc, decodetype_gc(gotype), 3*PtrSize+4); 1000 if(PtrSize == 8) 1001 adduintxx(gc, 0, 4); 1002 } else { 1003 //print("gcaddsym: %s %d <unknown type>\n", s->name, s->size); 1004 for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) { 1005 adduintxx(gc, GC_APTR, PtrSize); 1006 adduintxx(gc, off+a, PtrSize); 1007 } 1008 } 1009 } 1010 1011 void 1012 growdatsize(vlong *datsizep, Sym *s) 1013 { 1014 vlong datsize; 1015 1016 datsize = *datsizep; 1017 if(s->size < 0) 1018 diag("negative size (datsize = %lld, s->size = %lld)", datsize, s->size); 1019 if(datsize + s->size < datsize) 1020 diag("symbol too large (datsize = %lld, s->size = %lld)", datsize, s->size); 1021 *datsizep = datsize + s->size; 1022 } 1023 1024 void 1025 dodata(void) 1026 { 1027 int32 n; 1028 vlong datsize; 1029 Section *sect; 1030 Segment *segro; 1031 Sym *s, *last, **l; 1032 Sym *gcdata1, *gcbss1; 1033 1034 if(debug['v']) 1035 Bprint(&bso, "%5.2f dodata\n", cputime()); 1036 Bflush(&bso); 1037 1038 gcdata1 = lookup("gcdata", 0); 1039 gcbss1 = lookup("gcbss", 0); 1040 1041 // size of .data and .bss section. the zero value is later replaced by the actual size of the section. 1042 adduintxx(gcdata1, 0, PtrSize); 1043 adduintxx(gcbss1, 0, PtrSize); 1044 1045 last = nil; 1046 datap = nil; 1047 1048 for(s=allsym; s!=S; s=s->allsym) { 1049 if(!s->reachable || s->special) 1050 continue; 1051 if(STEXT < s->type && s->type < SXREF) { 1052 if(last == nil) 1053 datap = s; 1054 else 1055 last->next = s; 1056 s->next = nil; 1057 last = s; 1058 } 1059 } 1060 1061 for(s = datap; s != nil; s = s->next) { 1062 if(s->np > s->size) 1063 diag("%s: initialize bounds (%lld < %d)", 1064 s->name, (vlong)s->size, s->np); 1065 } 1066 1067 1068 /* 1069 * now that we have the datap list, but before we start 1070 * to assign addresses, record all the necessary 1071 * dynamic relocations. these will grow the relocation 1072 * symbol, which is itself data. 1073 * 1074 * on darwin, we need the symbol table numbers for dynreloc. 1075 */ 1076 if(HEADTYPE == Hdarwin) 1077 machosymorder(); 1078 dynreloc(); 1079 1080 /* some symbols may no longer belong in datap (Mach-O) */ 1081 for(l=&datap; (s=*l) != nil; ) { 1082 if(s->type <= STEXT || SXREF <= s->type) 1083 *l = s->next; 1084 else 1085 l = &s->next; 1086 } 1087 *l = nil; 1088 1089 datap = listsort(datap, datcmp, offsetof(Sym, next)); 1090 1091 /* 1092 * allocate sections. list is sorted by type, 1093 * so we can just walk it for each piece we want to emit. 1094 * segdata is processed before segtext, because we need 1095 * to see all symbols in the .data and .bss sections in order 1096 * to generate garbage collection information. 1097 */ 1098 1099 /* begin segdata */ 1100 1101 /* skip symbols belonging to segtext */ 1102 s = datap; 1103 for(; s != nil && s->type < SELFSECT; s = s->next) 1104 ; 1105 1106 /* writable ELF sections */ 1107 datsize = 0; 1108 for(; s != nil && s->type < SNOPTRDATA; s = s->next) { 1109 sect = addsection(&segdata, s->name, 06); 1110 sect->align = symalign(s); 1111 datsize = rnd(datsize, sect->align); 1112 sect->vaddr = datsize; 1113 s->sect = sect; 1114 s->type = SDATA; 1115 s->value = datsize - sect->vaddr; 1116 growdatsize(&datsize, s); 1117 sect->len = datsize - sect->vaddr; 1118 } 1119 1120 /* pointer-free data */ 1121 sect = addsection(&segdata, ".noptrdata", 06); 1122 sect->align = maxalign(s, SINITARR-1); 1123 datsize = rnd(datsize, sect->align); 1124 sect->vaddr = datsize; 1125 lookup("noptrdata", 0)->sect = sect; 1126 lookup("enoptrdata", 0)->sect = sect; 1127 for(; s != nil && s->type < SINITARR; s = s->next) { 1128 datsize = aligndatsize(datsize, s); 1129 s->sect = sect; 1130 s->type = SDATA; 1131 s->value = datsize - sect->vaddr; 1132 growdatsize(&datsize, s); 1133 } 1134 sect->len = datsize - sect->vaddr; 1135 1136 /* shared library initializer */ 1137 if(flag_shared) { 1138 sect = addsection(&segdata, ".init_array", 06); 1139 sect->align = maxalign(s, SINITARR); 1140 datsize = rnd(datsize, sect->align); 1141 sect->vaddr = datsize; 1142 for(; s != nil && s->type == SINITARR; s = s->next) { 1143 datsize = aligndatsize(datsize, s); 1144 s->sect = sect; 1145 s->value = datsize - sect->vaddr; 1146 growdatsize(&datsize, s); 1147 } 1148 sect->len = datsize - sect->vaddr; 1149 } 1150 1151 /* data */ 1152 sect = addsection(&segdata, ".data", 06); 1153 sect->align = maxalign(s, SBSS-1); 1154 datsize = rnd(datsize, sect->align); 1155 sect->vaddr = datsize; 1156 lookup("data", 0)->sect = sect; 1157 lookup("edata", 0)->sect = sect; 1158 for(; s != nil && s->type < SBSS; s = s->next) { 1159 if(s->type == SINITARR) { 1160 cursym = s; 1161 diag("unexpected symbol type %d", s->type); 1162 } 1163 s->sect = sect; 1164 s->type = SDATA; 1165 datsize = aligndatsize(datsize, s); 1166 s->value = datsize - sect->vaddr; 1167 gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc 1168 growdatsize(&datsize, s); 1169 } 1170 sect->len = datsize - sect->vaddr; 1171 1172 adduintxx(gcdata1, GC_END, PtrSize); 1173 setuintxx(gcdata1, 0, sect->len, PtrSize); 1174 1175 /* bss */ 1176 sect = addsection(&segdata, ".bss", 06); 1177 sect->align = maxalign(s, SNOPTRBSS-1); 1178 datsize = rnd(datsize, sect->align); 1179 sect->vaddr = datsize; 1180 lookup("bss", 0)->sect = sect; 1181 lookup("ebss", 0)->sect = sect; 1182 for(; s != nil && s->type < SNOPTRBSS; s = s->next) { 1183 s->sect = sect; 1184 datsize = aligndatsize(datsize, s); 1185 s->value = datsize - sect->vaddr; 1186 gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc 1187 growdatsize(&datsize, s); 1188 } 1189 sect->len = datsize - sect->vaddr; 1190 1191 adduintxx(gcbss1, GC_END, PtrSize); 1192 setuintxx(gcbss1, 0, sect->len, PtrSize); 1193 1194 /* pointer-free bss */ 1195 sect = addsection(&segdata, ".noptrbss", 06); 1196 sect->align = maxalign(s, SNOPTRBSS); 1197 datsize = rnd(datsize, sect->align); 1198 sect->vaddr = datsize; 1199 lookup("noptrbss", 0)->sect = sect; 1200 lookup("enoptrbss", 0)->sect = sect; 1201 for(; s != nil && s->type == SNOPTRBSS; s = s->next) { 1202 datsize = aligndatsize(datsize, s); 1203 s->sect = sect; 1204 s->value = datsize - sect->vaddr; 1205 growdatsize(&datsize, s); 1206 } 1207 sect->len = datsize - sect->vaddr; 1208 lookup("end", 0)->sect = sect; 1209 1210 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1211 if(datsize != (uint32)datsize) { 1212 diag("data or bss segment too large"); 1213 } 1214 1215 if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) { 1216 sect = addsection(&segdata, ".tbss", 06); 1217 sect->align = PtrSize; 1218 sect->vaddr = 0; 1219 datsize = 0; 1220 for(; s != nil && s->type == STLSBSS; s = s->next) { 1221 datsize = aligndatsize(datsize, s); 1222 s->sect = sect; 1223 s->value = datsize - sect->vaddr; 1224 growdatsize(&datsize, s); 1225 } 1226 sect->len = datsize; 1227 } 1228 1229 if(s != nil) { 1230 cursym = nil; 1231 diag("unexpected symbol type %d for %s", s->type, s->name); 1232 } 1233 1234 /* 1235 * We finished data, begin read-only data. 1236 * Not all systems support a separate read-only non-executable data section. 1237 * ELF systems do. 1238 * OS X and Plan 9 do not. 1239 * Windows PE may, but if so we have not implemented it. 1240 * And if we're using external linking mode, the point is moot, 1241 * since it's not our decision; that code expects the sections in 1242 * segtext. 1243 */ 1244 if(iself && linkmode == LinkInternal) 1245 segro = &segrodata; 1246 else 1247 segro = &segtext; 1248 1249 s = datap; 1250 1251 datsize = 0; 1252 1253 /* read-only executable ELF, Mach-O sections */ 1254 for(; s != nil && s->type < STYPE; s = s->next) { 1255 sect = addsection(&segtext, s->name, 04); 1256 sect->align = symalign(s); 1257 datsize = rnd(datsize, sect->align); 1258 sect->vaddr = datsize; 1259 s->sect = sect; 1260 s->type = SRODATA; 1261 s->value = datsize - sect->vaddr; 1262 growdatsize(&datsize, s); 1263 sect->len = datsize - sect->vaddr; 1264 } 1265 1266 /* read-only data */ 1267 sect = addsection(segro, ".rodata", 04); 1268 sect->align = maxalign(s, STYPELINK-1); 1269 datsize = rnd(datsize, sect->align); 1270 sect->vaddr = 0; 1271 lookup("rodata", 0)->sect = sect; 1272 lookup("erodata", 0)->sect = sect; 1273 for(; s != nil && s->type < STYPELINK; s = s->next) { 1274 datsize = aligndatsize(datsize, s); 1275 s->sect = sect; 1276 s->type = SRODATA; 1277 s->value = datsize - sect->vaddr; 1278 growdatsize(&datsize, s); 1279 } 1280 sect->len = datsize - sect->vaddr; 1281 1282 /* typelink */ 1283 sect = addsection(segro, ".typelink", 04); 1284 sect->align = maxalign(s, STYPELINK); 1285 datsize = rnd(datsize, sect->align); 1286 sect->vaddr = datsize; 1287 lookup("typelink", 0)->sect = sect; 1288 lookup("etypelink", 0)->sect = sect; 1289 for(; s != nil && s->type == STYPELINK; s = s->next) { 1290 datsize = aligndatsize(datsize, s); 1291 s->sect = sect; 1292 s->type = SRODATA; 1293 s->value = datsize - sect->vaddr; 1294 growdatsize(&datsize, s); 1295 } 1296 sect->len = datsize - sect->vaddr; 1297 1298 /* gosymtab */ 1299 sect = addsection(segro, ".gosymtab", 04); 1300 sect->align = maxalign(s, SPCLNTAB-1); 1301 datsize = rnd(datsize, sect->align); 1302 sect->vaddr = datsize; 1303 lookup("symtab", 0)->sect = sect; 1304 lookup("esymtab", 0)->sect = sect; 1305 for(; s != nil && s->type < SPCLNTAB; s = s->next) { 1306 datsize = aligndatsize(datsize, s); 1307 s->sect = sect; 1308 s->type = SRODATA; 1309 s->value = datsize - sect->vaddr; 1310 growdatsize(&datsize, s); 1311 } 1312 sect->len = datsize - sect->vaddr; 1313 1314 /* gopclntab */ 1315 sect = addsection(segro, ".gopclntab", 04); 1316 sect->align = maxalign(s, SELFROSECT-1); 1317 datsize = rnd(datsize, sect->align); 1318 sect->vaddr = datsize; 1319 lookup("pclntab", 0)->sect = sect; 1320 lookup("epclntab", 0)->sect = sect; 1321 for(; s != nil && s->type < SELFROSECT; s = s->next) { 1322 datsize = aligndatsize(datsize, s); 1323 s->sect = sect; 1324 s->type = SRODATA; 1325 s->value = datsize - sect->vaddr; 1326 growdatsize(&datsize, s); 1327 } 1328 sect->len = datsize - sect->vaddr; 1329 1330 /* read-only ELF, Mach-O sections */ 1331 for(; s != nil && s->type < SELFSECT; s = s->next) { 1332 sect = addsection(segro, s->name, 04); 1333 sect->align = symalign(s); 1334 datsize = rnd(datsize, sect->align); 1335 sect->vaddr = datsize; 1336 s->sect = sect; 1337 s->type = SRODATA; 1338 s->value = datsize - sect->vaddr; 1339 growdatsize(&datsize, s); 1340 sect->len = datsize - sect->vaddr; 1341 } 1342 1343 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1344 if(datsize != (uint32)datsize) { 1345 diag("read-only data segment too large"); 1346 } 1347 1348 /* number the sections */ 1349 n = 1; 1350 for(sect = segtext.sect; sect != nil; sect = sect->next) 1351 sect->extnum = n++; 1352 for(sect = segrodata.sect; sect != nil; sect = sect->next) 1353 sect->extnum = n++; 1354 for(sect = segdata.sect; sect != nil; sect = sect->next) 1355 sect->extnum = n++; 1356 } 1357 1358 // assign addresses to text 1359 void 1360 textaddress(void) 1361 { 1362 uvlong va; 1363 Prog *p; 1364 Section *sect; 1365 Sym *sym, *sub; 1366 1367 addsection(&segtext, ".text", 05); 1368 1369 // Assign PCs in text segment. 1370 // Could parallelize, by assigning to text 1371 // and then letting threads copy down, but probably not worth it. 1372 sect = segtext.sect; 1373 sect->align = FuncAlign; 1374 lookup("text", 0)->sect = sect; 1375 lookup("etext", 0)->sect = sect; 1376 va = INITTEXT; 1377 sect->vaddr = va; 1378 for(sym = textp; sym != nil; sym = sym->next) { 1379 sym->sect = sect; 1380 if(sym->type & SSUB) 1381 continue; 1382 if(sym->align != 0) 1383 va = rnd(va, sym->align); 1384 else if(sym->text != P) 1385 va = rnd(va, FuncAlign); 1386 sym->value = 0; 1387 for(sub = sym; sub != S; sub = sub->sub) { 1388 sub->value += va; 1389 for(p = sub->text; p != P; p = p->link) 1390 p->pc += sub->value; 1391 } 1392 if(sym->size == 0 && sym->sub != S) { 1393 cursym = sym; 1394 } 1395 va += sym->size; 1396 } 1397 sect->len = va - sect->vaddr; 1398 } 1399 1400 // assign addresses 1401 void 1402 address(void) 1403 { 1404 Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss; 1405 Section *typelink; 1406 Sym *sym, *sub; 1407 uvlong va; 1408 vlong vlen; 1409 1410 va = INITTEXT; 1411 segtext.rwx = 05; 1412 segtext.vaddr = va; 1413 segtext.fileoff = HEADR; 1414 for(s=segtext.sect; s != nil; s=s->next) { 1415 //print("%s at %#llux + %#llux\n", s->name, va, (vlong)s->len); 1416 va = rnd(va, s->align); 1417 s->vaddr = va; 1418 va += s->len; 1419 } 1420 segtext.len = va - INITTEXT; 1421 segtext.filelen = segtext.len; 1422 1423 if(segrodata.sect != nil) { 1424 // align to page boundary so as not to mix 1425 // rodata and executable text. 1426 va = rnd(va, INITRND); 1427 1428 segrodata.rwx = 04; 1429 segrodata.vaddr = va; 1430 segrodata.fileoff = va - segtext.vaddr + segtext.fileoff; 1431 segrodata.filelen = 0; 1432 for(s=segrodata.sect; s != nil; s=s->next) { 1433 va = rnd(va, s->align); 1434 s->vaddr = va; 1435 va += s->len; 1436 } 1437 segrodata.len = va - segrodata.vaddr; 1438 segrodata.filelen = segrodata.len; 1439 } 1440 1441 va = rnd(va, INITRND); 1442 segdata.rwx = 06; 1443 segdata.vaddr = va; 1444 segdata.fileoff = va - segtext.vaddr + segtext.fileoff; 1445 segdata.filelen = 0; 1446 if(HEADTYPE == Hwindows) 1447 segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN); 1448 if(HEADTYPE == Hplan9x64 || HEADTYPE == Hplan9x32) 1449 segdata.fileoff = segtext.fileoff + segtext.filelen; 1450 data = nil; 1451 noptr = nil; 1452 bss = nil; 1453 noptrbss = nil; 1454 for(s=segdata.sect; s != nil; s=s->next) { 1455 vlen = s->len; 1456 if(s->next) 1457 vlen = s->next->vaddr - s->vaddr; 1458 s->vaddr = va; 1459 va += vlen; 1460 segdata.len = va - segdata.vaddr; 1461 if(strcmp(s->name, ".data") == 0) 1462 data = s; 1463 if(strcmp(s->name, ".noptrdata") == 0) 1464 noptr = s; 1465 if(strcmp(s->name, ".bss") == 0) 1466 bss = s; 1467 if(strcmp(s->name, ".noptrbss") == 0) 1468 noptrbss = s; 1469 } 1470 segdata.filelen = bss->vaddr - segdata.vaddr; 1471 1472 text = segtext.sect; 1473 if(segrodata.sect) 1474 rodata = segrodata.sect; 1475 else 1476 rodata = text->next; 1477 typelink = rodata->next; 1478 symtab = typelink->next; 1479 pclntab = symtab->next; 1480 1481 for(sym = datap; sym != nil; sym = sym->next) { 1482 cursym = sym; 1483 sym->value += sym->sect->vaddr; 1484 for(sub = sym->sub; sub != nil; sub = sub->sub) 1485 sub->value += sym->value; 1486 } 1487 1488 xdefine("text", STEXT, text->vaddr); 1489 xdefine("etext", STEXT, text->vaddr + text->len); 1490 xdefine("rodata", SRODATA, rodata->vaddr); 1491 xdefine("erodata", SRODATA, rodata->vaddr + rodata->len); 1492 xdefine("typelink", SRODATA, typelink->vaddr); 1493 xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len); 1494 1495 sym = lookup("gcdata", 0); 1496 xdefine("egcdata", SRODATA, symaddr(sym) + sym->size); 1497 lookup("egcdata", 0)->sect = sym->sect; 1498 1499 sym = lookup("gcbss", 0); 1500 xdefine("egcbss", SRODATA, symaddr(sym) + sym->size); 1501 lookup("egcbss", 0)->sect = sym->sect; 1502 1503 xdefine("symtab", SRODATA, symtab->vaddr); 1504 xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len); 1505 xdefine("pclntab", SRODATA, pclntab->vaddr); 1506 xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len); 1507 xdefine("noptrdata", SNOPTRDATA, noptr->vaddr); 1508 xdefine("enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len); 1509 xdefine("bss", SBSS, bss->vaddr); 1510 xdefine("ebss", SBSS, bss->vaddr + bss->len); 1511 xdefine("data", SDATA, data->vaddr); 1512 xdefine("edata", SDATA, data->vaddr + data->len); 1513 xdefine("noptrbss", SNOPTRBSS, noptrbss->vaddr); 1514 xdefine("enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len); 1515 xdefine("end", SBSS, segdata.vaddr + segdata.len); 1516 }