github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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->np > s->maxp) { 380 cursym = s; 381 diag("corrupt symbol data: np=%lld > maxp=%lld", (vlong)s->np, (vlong)s->maxp); 382 errorexit(); 383 } 384 385 if(s->maxp < siz) { 386 if(s->maxp == 0) 387 s->maxp = 8; 388 while(s->maxp < siz) 389 s->maxp <<= 1; 390 s->p = erealloc(s->p, s->maxp); 391 memset(s->p+s->np, 0, s->maxp-s->np); 392 } 393 s->np = siz; 394 } 395 396 void 397 savedata(Sym *s, Prog *p, char *pn) 398 { 399 int32 off, siz, i, fl; 400 uchar *cast; 401 vlong o; 402 Reloc *r; 403 404 off = p->from.offset; 405 siz = p->datasize; 406 if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100) 407 mangle(pn); 408 symgrow(s, off+siz); 409 410 switch(p->to.type) { 411 default: 412 diag("bad data: %P", p); 413 break; 414 415 case D_FCONST: 416 switch(siz) { 417 default: 418 case 4: 419 fl = ieeedtof(&p->to.ieee); 420 cast = (uchar*)&fl; 421 for(i=0; i<4; i++) 422 s->p[off+i] = cast[fnuxi4[i]]; 423 break; 424 case 8: 425 cast = (uchar*)&p->to.ieee; 426 for(i=0; i<8; i++) 427 s->p[off+i] = cast[fnuxi8[i]]; 428 break; 429 } 430 break; 431 432 case D_SCONST: 433 for(i=0; i<siz; i++) 434 s->p[off+i] = p->to.scon[i]; 435 break; 436 437 case D_CONST: 438 if(p->to.sym) 439 goto Addr; 440 o = p->to.offset; 441 fl = o; 442 cast = (uchar*)&fl; 443 switch(siz) { 444 default: 445 diag("bad nuxi %d\n%P", siz, p); 446 break; 447 case 1: 448 s->p[off] = cast[inuxi1[0]]; 449 break; 450 case 2: 451 for(i=0; i<2; i++) 452 s->p[off+i] = cast[inuxi2[i]]; 453 break; 454 case 4: 455 for(i=0; i<4; i++) 456 s->p[off+i] = cast[inuxi4[i]]; 457 break; 458 case 8: 459 cast = (uchar*)&o; 460 for(i=0; i<8; i++) 461 s->p[off+i] = cast[inuxi8[i]]; 462 break; 463 } 464 break; 465 466 case D_ADDR: 467 case D_SIZE: 468 Addr: 469 r = addrel(s); 470 r->off = off; 471 r->siz = siz; 472 r->sym = p->to.sym; 473 r->type = p->to.type; 474 if(r->type != D_SIZE) 475 r->type = D_ADDR; 476 r->add = p->to.offset; 477 break; 478 } 479 } 480 481 static void 482 blk(Sym *start, int32 addr, int32 size) 483 { 484 Sym *sym; 485 int32 eaddr; 486 uchar *p, *ep; 487 488 for(sym = start; sym != nil; sym = sym->next) 489 if(!(sym->type&SSUB) && sym->value >= addr) 490 break; 491 492 eaddr = addr+size; 493 for(; sym != nil; sym = sym->next) { 494 if(sym->type&SSUB) 495 continue; 496 if(sym->value >= eaddr) 497 break; 498 if(sym->value < addr) { 499 diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type); 500 errorexit(); 501 } 502 cursym = sym; 503 for(; addr < sym->value; addr++) 504 cput(0); 505 p = sym->p; 506 ep = p + sym->np; 507 while(p < ep) 508 cput(*p++); 509 addr += sym->np; 510 for(; addr < sym->value+sym->size; addr++) 511 cput(0); 512 if(addr != sym->value+sym->size) { 513 diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size); 514 errorexit(); 515 } 516 } 517 518 for(; addr < eaddr; addr++) 519 cput(0); 520 cflush(); 521 } 522 523 void 524 codeblk(int32 addr, int32 size) 525 { 526 Sym *sym; 527 int32 eaddr, n, epc; 528 Prog *p; 529 uchar *q; 530 531 if(debug['a']) 532 Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos()); 533 534 blk(textp, addr, size); 535 536 /* again for printing */ 537 if(!debug['a']) 538 return; 539 540 for(sym = textp; sym != nil; sym = sym->next) { 541 if(!sym->reachable) 542 continue; 543 if(sym->value >= addr) 544 break; 545 } 546 547 eaddr = addr + size; 548 for(; sym != nil; sym = sym->next) { 549 if(!sym->reachable) 550 continue; 551 if(sym->value >= eaddr) 552 break; 553 554 if(addr < sym->value) { 555 Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr); 556 for(; addr < sym->value; addr++) 557 Bprint(&bso, " %.2ux", 0); 558 Bprint(&bso, "\n"); 559 } 560 p = sym->text; 561 if(p == nil) { 562 Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name); 563 n = sym->size; 564 q = sym->p; 565 566 while(n >= 16) { 567 Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q); 568 addr += 16; 569 q += 16; 570 n -= 16; 571 } 572 if(n > 0) 573 Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q); 574 addr += n; 575 continue; 576 } 577 578 Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p); 579 for(p = p->link; p != P; p = p->link) { 580 if(p->link != P) 581 epc = p->link->pc; 582 else 583 epc = sym->value + sym->size; 584 Bprint(&bso, "%.6llux\t", (uvlong)p->pc); 585 q = sym->p + p->pc - sym->value; 586 n = epc - p->pc; 587 Bprint(&bso, "%-20.*I | %P\n", (int)n, q, p); 588 addr += n; 589 } 590 } 591 592 if(addr < eaddr) { 593 Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr); 594 for(; addr < eaddr; addr++) 595 Bprint(&bso, " %.2ux", 0); 596 } 597 Bflush(&bso); 598 } 599 600 void 601 datblk(int32 addr, int32 size) 602 { 603 Sym *sym; 604 int32 i, eaddr; 605 uchar *p, *ep; 606 char *typ, *rsname; 607 Reloc *r; 608 609 if(debug['a']) 610 Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos()); 611 612 blk(datap, addr, size); 613 614 /* again for printing */ 615 if(!debug['a']) 616 return; 617 618 for(sym = datap; sym != nil; sym = sym->next) 619 if(sym->value >= addr) 620 break; 621 622 eaddr = addr + size; 623 for(; sym != nil; sym = sym->next) { 624 if(sym->value >= eaddr) 625 break; 626 if(addr < sym->value) { 627 Bprint(&bso, "\t%.8ux| 00 ...\n", addr); 628 addr = sym->value; 629 } 630 Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr); 631 p = sym->p; 632 ep = p + sym->np; 633 while(p < ep) { 634 if(p > sym->p && (int)(p-sym->p)%16 == 0) 635 Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p))); 636 Bprint(&bso, " %.2ux", *p++); 637 } 638 addr += sym->np; 639 for(; addr < sym->value+sym->size; addr++) 640 Bprint(&bso, " %.2ux", 0); 641 Bprint(&bso, "\n"); 642 643 if(linkmode == LinkExternal) { 644 for(i=0; i<sym->nr; i++) { 645 r = &sym->r[i]; 646 rsname = ""; 647 if(r->sym) 648 rsname = r->sym->name; 649 typ = "?"; 650 switch(r->type) { 651 case D_ADDR: 652 typ = "addr"; 653 break; 654 case D_PCREL: 655 typ = "pcrel"; 656 break; 657 } 658 Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n", 659 (uint)(sym->value+r->off), r->siz, typ, rsname, (vlong)r->add, (vlong)(r->sym->value+r->add)); 660 } 661 } 662 } 663 664 if(addr < eaddr) 665 Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr); 666 Bprint(&bso, "\t%.8ux|\n", (uint)eaddr); 667 } 668 669 void 670 strnput(char *s, int n) 671 { 672 for(; n > 0 && *s; s++) { 673 cput(*s); 674 n--; 675 } 676 while(n > 0) { 677 cput(0); 678 n--; 679 } 680 } 681 682 void 683 addstrdata(char *name, char *value) 684 { 685 Sym *s, *sp; 686 char *p; 687 688 p = smprint("%s.str", name); 689 sp = lookup(p, 0); 690 free(p); 691 addstring(sp, value); 692 693 s = lookup(name, 0); 694 s->size = 0; 695 s->dupok = 1; 696 addaddr(s, sp); 697 adduint32(s, strlen(value)); 698 if(PtrSize == 8) 699 adduint32(s, 0); // round struct to pointer width 700 701 // in case reachability has already been computed 702 sp->reachable = s->reachable; 703 } 704 705 vlong 706 addstring(Sym *s, char *str) 707 { 708 int n; 709 int32 r; 710 711 if(s->type == 0) 712 s->type = SNOPTRDATA; 713 s->reachable = 1; 714 r = s->size; 715 n = strlen(str)+1; 716 if(strcmp(s->name, ".shstrtab") == 0) 717 elfsetstring(str, r); 718 symgrow(s, r+n); 719 memmove(s->p+r, str, n); 720 s->size += n; 721 return r; 722 } 723 724 vlong 725 setuintxx(Sym *s, vlong off, uint64 v, vlong wid) 726 { 727 int32 i, fl; 728 vlong o; 729 uchar *cast; 730 731 if(s->type == 0) 732 s->type = SDATA; 733 s->reachable = 1; 734 if(s->size < off+wid) { 735 s->size = off+wid; 736 symgrow(s, s->size); 737 } 738 fl = v; 739 cast = (uchar*)&fl; 740 switch(wid) { 741 case 1: 742 s->p[off] = cast[inuxi1[0]]; 743 break; 744 case 2: 745 for(i=0; i<2; i++) 746 s->p[off+i] = cast[inuxi2[i]]; 747 break; 748 case 4: 749 for(i=0; i<4; i++) 750 s->p[off+i] = cast[inuxi4[i]]; 751 break; 752 case 8: 753 o = v; 754 cast = (uchar*)&o; 755 for(i=0; i<8; i++) 756 s->p[off+i] = cast[inuxi8[i]]; 757 break; 758 } 759 return off+wid; 760 } 761 762 vlong 763 adduintxx(Sym *s, uint64 v, int wid) 764 { 765 vlong off; 766 767 off = s->size; 768 setuintxx(s, off, v, wid); 769 return off; 770 } 771 772 vlong 773 adduint8(Sym *s, uint8 v) 774 { 775 return adduintxx(s, v, 1); 776 } 777 778 vlong 779 adduint16(Sym *s, uint16 v) 780 { 781 return adduintxx(s, v, 2); 782 } 783 784 vlong 785 adduint32(Sym *s, uint32 v) 786 { 787 return adduintxx(s, v, 4); 788 } 789 790 vlong 791 adduint64(Sym *s, uint64 v) 792 { 793 return adduintxx(s, v, 8); 794 } 795 796 vlong 797 setuint8(Sym *s, vlong r, uint8 v) 798 { 799 return setuintxx(s, r, v, 1); 800 } 801 802 vlong 803 setuint16(Sym *s, vlong r, uint16 v) 804 { 805 return setuintxx(s, r, v, 2); 806 } 807 808 vlong 809 setuint32(Sym *s, vlong r, uint32 v) 810 { 811 return setuintxx(s, r, v, 4); 812 } 813 814 vlong 815 setuint64(Sym *s, vlong r, uint64 v) 816 { 817 return setuintxx(s, r, v, 8); 818 } 819 820 vlong 821 addaddrplus(Sym *s, Sym *t, vlong add) 822 { 823 vlong i; 824 Reloc *r; 825 826 if(s->type == 0) 827 s->type = SDATA; 828 s->reachable = 1; 829 i = s->size; 830 s->size += PtrSize; 831 symgrow(s, s->size); 832 r = addrel(s); 833 r->sym = t; 834 r->off = i; 835 r->siz = PtrSize; 836 r->type = D_ADDR; 837 r->add = add; 838 return i + r->siz; 839 } 840 841 static vlong 842 addaddrplus4(Sym *s, Sym *t, vlong add) 843 { 844 vlong i; 845 Reloc *r; 846 847 if(s->type == 0) 848 s->type = SDATA; 849 s->reachable = 1; 850 i = s->size; 851 s->size += 4; 852 symgrow(s, s->size); 853 r = addrel(s); 854 r->sym = t; 855 r->off = i; 856 r->siz = 4; 857 r->type = D_ADDR; 858 r->add = add; 859 return i + r->siz; 860 } 861 862 vlong 863 addpcrelplus(Sym *s, Sym *t, vlong add) 864 { 865 vlong i; 866 Reloc *r; 867 868 if(s->type == 0) 869 s->type = SDATA; 870 s->reachable = 1; 871 i = s->size; 872 s->size += 4; 873 symgrow(s, s->size); 874 r = addrel(s); 875 r->sym = t; 876 r->off = i; 877 r->add = add; 878 r->type = D_PCREL; 879 r->siz = 4; 880 return i + r->siz; 881 } 882 883 vlong 884 addaddr(Sym *s, Sym *t) 885 { 886 return addaddrplus(s, t, 0); 887 } 888 889 vlong 890 setaddrplus(Sym *s, vlong off, Sym *t, vlong add) 891 { 892 Reloc *r; 893 894 if(s->type == 0) 895 s->type = SDATA; 896 s->reachable = 1; 897 if(off+PtrSize > s->size) { 898 s->size = off + PtrSize; 899 symgrow(s, s->size); 900 } 901 r = addrel(s); 902 r->sym = t; 903 r->off = off; 904 r->siz = PtrSize; 905 r->type = D_ADDR; 906 r->add = add; 907 return off + r->siz; 908 } 909 910 vlong 911 setaddr(Sym *s, vlong off, Sym *t) 912 { 913 return setaddrplus(s, off, t, 0); 914 } 915 916 vlong 917 addsize(Sym *s, Sym *t) 918 { 919 vlong i; 920 Reloc *r; 921 922 if(s->type == 0) 923 s->type = SDATA; 924 s->reachable = 1; 925 i = s->size; 926 s->size += PtrSize; 927 symgrow(s, s->size); 928 r = addrel(s); 929 r->sym = t; 930 r->off = i; 931 r->siz = PtrSize; 932 r->type = D_SIZE; 933 return i + r->siz; 934 } 935 936 void 937 dosymtype(void) 938 { 939 Sym *s; 940 941 for(s = allsym; s != nil; s = s->allsym) { 942 if(s->np > 0) { 943 if(s->type == SBSS) 944 s->type = SDATA; 945 if(s->type == SNOPTRBSS) 946 s->type = SNOPTRDATA; 947 } 948 } 949 } 950 951 static int32 952 symalign(Sym *s) 953 { 954 int32 align; 955 956 if(s->align != 0) 957 return s->align; 958 959 align = MaxAlign; 960 while(align > s->size && align > 1) 961 align >>= 1; 962 if(align < s->align) 963 align = s->align; 964 return align; 965 } 966 967 static vlong 968 aligndatsize(vlong datsize, Sym *s) 969 { 970 return rnd(datsize, symalign(s)); 971 } 972 973 // maxalign returns the maximum required alignment for 974 // the list of symbols s; the list stops when s->type exceeds type. 975 static int32 976 maxalign(Sym *s, int type) 977 { 978 int32 align, max; 979 980 max = 0; 981 for(; s != S && s->type <= type; s = s->next) { 982 align = symalign(s); 983 if(max < align) 984 max = align; 985 } 986 return max; 987 } 988 989 static void 990 gcaddsym(Sym *gc, Sym *s, vlong off) 991 { 992 vlong a; 993 Sym *gotype; 994 995 if(s->size < PtrSize) 996 return; 997 if(strcmp(s->name, ".string") == 0) 998 return; 999 1000 gotype = s->gotype; 1001 if(gotype != nil) { 1002 //print("gcaddsym: %s %d %s\n", s->name, s->size, gotype->name); 1003 adduintxx(gc, GC_CALL, PtrSize); 1004 adduintxx(gc, off, PtrSize); 1005 addpcrelplus(gc, decodetype_gc(gotype), 3*PtrSize+4); 1006 if(PtrSize == 8) 1007 adduintxx(gc, 0, 4); 1008 } else { 1009 //print("gcaddsym: %s %d <unknown type>\n", s->name, s->size); 1010 for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) { 1011 adduintxx(gc, GC_APTR, PtrSize); 1012 adduintxx(gc, off+a, PtrSize); 1013 } 1014 } 1015 } 1016 1017 void 1018 growdatsize(vlong *datsizep, Sym *s) 1019 { 1020 vlong datsize; 1021 1022 datsize = *datsizep; 1023 if(s->size < 0) 1024 diag("negative size (datsize = %lld, s->size = %lld)", datsize, s->size); 1025 if(datsize + s->size < datsize) 1026 diag("symbol too large (datsize = %lld, s->size = %lld)", datsize, s->size); 1027 *datsizep = datsize + s->size; 1028 } 1029 1030 void 1031 dodata(void) 1032 { 1033 int32 n; 1034 vlong datsize; 1035 Section *sect; 1036 Segment *segro; 1037 Sym *s, *last, **l; 1038 Sym *gcdata1, *gcbss1; 1039 1040 if(debug['v']) 1041 Bprint(&bso, "%5.2f dodata\n", cputime()); 1042 Bflush(&bso); 1043 1044 gcdata1 = lookup("gcdata", 0); 1045 gcbss1 = lookup("gcbss", 0); 1046 1047 // size of .data and .bss section. the zero value is later replaced by the actual size of the section. 1048 adduintxx(gcdata1, 0, PtrSize); 1049 adduintxx(gcbss1, 0, PtrSize); 1050 1051 last = nil; 1052 datap = nil; 1053 1054 for(s=allsym; s!=S; s=s->allsym) { 1055 if(!s->reachable || s->special) 1056 continue; 1057 if(STEXT < s->type && s->type < SXREF) { 1058 if(last == nil) 1059 datap = s; 1060 else 1061 last->next = s; 1062 s->next = nil; 1063 last = s; 1064 } 1065 } 1066 1067 for(s = datap; s != nil; s = s->next) { 1068 if(s->np > s->size) 1069 diag("%s: initialize bounds (%lld < %d)", 1070 s->name, (vlong)s->size, s->np); 1071 } 1072 1073 1074 /* 1075 * now that we have the datap list, but before we start 1076 * to assign addresses, record all the necessary 1077 * dynamic relocations. these will grow the relocation 1078 * symbol, which is itself data. 1079 * 1080 * on darwin, we need the symbol table numbers for dynreloc. 1081 */ 1082 if(HEADTYPE == Hdarwin) 1083 machosymorder(); 1084 dynreloc(); 1085 1086 /* some symbols may no longer belong in datap (Mach-O) */ 1087 for(l=&datap; (s=*l) != nil; ) { 1088 if(s->type <= STEXT || SXREF <= s->type) 1089 *l = s->next; 1090 else 1091 l = &s->next; 1092 } 1093 *l = nil; 1094 1095 datap = listsort(datap, datcmp, offsetof(Sym, next)); 1096 1097 /* 1098 * allocate sections. list is sorted by type, 1099 * so we can just walk it for each piece we want to emit. 1100 * segdata is processed before segtext, because we need 1101 * to see all symbols in the .data and .bss sections in order 1102 * to generate garbage collection information. 1103 */ 1104 1105 /* begin segdata */ 1106 1107 /* skip symbols belonging to segtext */ 1108 s = datap; 1109 for(; s != nil && s->type < SELFSECT; s = s->next) 1110 ; 1111 1112 /* writable ELF sections */ 1113 datsize = 0; 1114 for(; s != nil && s->type < SNOPTRDATA; s = s->next) { 1115 sect = addsection(&segdata, s->name, 06); 1116 sect->align = symalign(s); 1117 datsize = rnd(datsize, sect->align); 1118 sect->vaddr = datsize; 1119 s->sect = sect; 1120 s->type = SDATA; 1121 s->value = datsize - sect->vaddr; 1122 growdatsize(&datsize, s); 1123 sect->len = datsize - sect->vaddr; 1124 } 1125 1126 /* pointer-free data */ 1127 sect = addsection(&segdata, ".noptrdata", 06); 1128 sect->align = maxalign(s, SINITARR-1); 1129 datsize = rnd(datsize, sect->align); 1130 sect->vaddr = datsize; 1131 lookup("noptrdata", 0)->sect = sect; 1132 lookup("enoptrdata", 0)->sect = sect; 1133 for(; s != nil && s->type < SINITARR; s = s->next) { 1134 datsize = aligndatsize(datsize, s); 1135 s->sect = sect; 1136 s->type = SDATA; 1137 s->value = datsize - sect->vaddr; 1138 growdatsize(&datsize, s); 1139 } 1140 sect->len = datsize - sect->vaddr; 1141 1142 /* shared library initializer */ 1143 if(flag_shared) { 1144 sect = addsection(&segdata, ".init_array", 06); 1145 sect->align = maxalign(s, SINITARR); 1146 datsize = rnd(datsize, sect->align); 1147 sect->vaddr = datsize; 1148 for(; s != nil && s->type == SINITARR; s = s->next) { 1149 datsize = aligndatsize(datsize, s); 1150 s->sect = sect; 1151 s->value = datsize - sect->vaddr; 1152 growdatsize(&datsize, s); 1153 } 1154 sect->len = datsize - sect->vaddr; 1155 } 1156 1157 /* data */ 1158 sect = addsection(&segdata, ".data", 06); 1159 sect->align = maxalign(s, SBSS-1); 1160 datsize = rnd(datsize, sect->align); 1161 sect->vaddr = datsize; 1162 lookup("data", 0)->sect = sect; 1163 lookup("edata", 0)->sect = sect; 1164 for(; s != nil && s->type < SBSS; s = s->next) { 1165 if(s->type == SINITARR) { 1166 cursym = s; 1167 diag("unexpected symbol type %d", s->type); 1168 } 1169 s->sect = sect; 1170 s->type = SDATA; 1171 datsize = aligndatsize(datsize, s); 1172 s->value = datsize - sect->vaddr; 1173 gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc 1174 growdatsize(&datsize, s); 1175 } 1176 sect->len = datsize - sect->vaddr; 1177 1178 adduintxx(gcdata1, GC_END, PtrSize); 1179 setuintxx(gcdata1, 0, sect->len, PtrSize); 1180 1181 /* bss */ 1182 sect = addsection(&segdata, ".bss", 06); 1183 sect->align = maxalign(s, SNOPTRBSS-1); 1184 datsize = rnd(datsize, sect->align); 1185 sect->vaddr = datsize; 1186 lookup("bss", 0)->sect = sect; 1187 lookup("ebss", 0)->sect = sect; 1188 for(; s != nil && s->type < SNOPTRBSS; s = s->next) { 1189 s->sect = sect; 1190 datsize = aligndatsize(datsize, s); 1191 s->value = datsize - sect->vaddr; 1192 gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc 1193 growdatsize(&datsize, s); 1194 } 1195 sect->len = datsize - sect->vaddr; 1196 1197 adduintxx(gcbss1, GC_END, PtrSize); 1198 setuintxx(gcbss1, 0, sect->len, PtrSize); 1199 1200 /* pointer-free bss */ 1201 sect = addsection(&segdata, ".noptrbss", 06); 1202 sect->align = maxalign(s, SNOPTRBSS); 1203 datsize = rnd(datsize, sect->align); 1204 sect->vaddr = datsize; 1205 lookup("noptrbss", 0)->sect = sect; 1206 lookup("enoptrbss", 0)->sect = sect; 1207 for(; s != nil && s->type == SNOPTRBSS; s = s->next) { 1208 datsize = aligndatsize(datsize, s); 1209 s->sect = sect; 1210 s->value = datsize - sect->vaddr; 1211 growdatsize(&datsize, s); 1212 } 1213 sect->len = datsize - sect->vaddr; 1214 lookup("end", 0)->sect = sect; 1215 1216 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1217 if(datsize != (uint32)datsize) { 1218 diag("data or bss segment too large"); 1219 } 1220 1221 if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) { 1222 sect = addsection(&segdata, ".tbss", 06); 1223 sect->align = PtrSize; 1224 sect->vaddr = 0; 1225 datsize = 0; 1226 for(; s != nil && s->type == STLSBSS; s = s->next) { 1227 datsize = aligndatsize(datsize, s); 1228 s->sect = sect; 1229 s->value = datsize - sect->vaddr; 1230 growdatsize(&datsize, s); 1231 } 1232 sect->len = datsize; 1233 } 1234 1235 if(s != nil) { 1236 cursym = nil; 1237 diag("unexpected symbol type %d for %s", s->type, s->name); 1238 } 1239 1240 /* 1241 * We finished data, begin read-only data. 1242 * Not all systems support a separate read-only non-executable data section. 1243 * ELF systems do. 1244 * OS X and Plan 9 do not. 1245 * Windows PE may, but if so we have not implemented it. 1246 * And if we're using external linking mode, the point is moot, 1247 * since it's not our decision; that code expects the sections in 1248 * segtext. 1249 */ 1250 if(iself && linkmode == LinkInternal) 1251 segro = &segrodata; 1252 else 1253 segro = &segtext; 1254 1255 s = datap; 1256 1257 datsize = 0; 1258 1259 /* read-only executable ELF, Mach-O sections */ 1260 for(; s != nil && s->type < STYPE; s = s->next) { 1261 sect = addsection(&segtext, s->name, 04); 1262 sect->align = symalign(s); 1263 datsize = rnd(datsize, sect->align); 1264 sect->vaddr = datsize; 1265 s->sect = sect; 1266 s->type = SRODATA; 1267 s->value = datsize - sect->vaddr; 1268 growdatsize(&datsize, s); 1269 sect->len = datsize - sect->vaddr; 1270 } 1271 1272 /* read-only data */ 1273 sect = addsection(segro, ".rodata", 04); 1274 sect->align = maxalign(s, STYPELINK-1); 1275 datsize = rnd(datsize, sect->align); 1276 sect->vaddr = 0; 1277 lookup("rodata", 0)->sect = sect; 1278 lookup("erodata", 0)->sect = sect; 1279 for(; s != nil && s->type < STYPELINK; s = s->next) { 1280 datsize = aligndatsize(datsize, s); 1281 s->sect = sect; 1282 s->type = SRODATA; 1283 s->value = datsize - sect->vaddr; 1284 growdatsize(&datsize, s); 1285 } 1286 sect->len = datsize - sect->vaddr; 1287 1288 /* typelink */ 1289 sect = addsection(segro, ".typelink", 04); 1290 sect->align = maxalign(s, STYPELINK); 1291 datsize = rnd(datsize, sect->align); 1292 sect->vaddr = datsize; 1293 lookup("typelink", 0)->sect = sect; 1294 lookup("etypelink", 0)->sect = sect; 1295 for(; s != nil && s->type == STYPELINK; s = s->next) { 1296 datsize = aligndatsize(datsize, s); 1297 s->sect = sect; 1298 s->type = SRODATA; 1299 s->value = datsize - sect->vaddr; 1300 growdatsize(&datsize, s); 1301 } 1302 sect->len = datsize - sect->vaddr; 1303 1304 /* gosymtab */ 1305 sect = addsection(segro, ".gosymtab", 04); 1306 sect->align = maxalign(s, SPCLNTAB-1); 1307 datsize = rnd(datsize, sect->align); 1308 sect->vaddr = datsize; 1309 lookup("symtab", 0)->sect = sect; 1310 lookup("esymtab", 0)->sect = sect; 1311 for(; s != nil && s->type < SPCLNTAB; s = s->next) { 1312 datsize = aligndatsize(datsize, s); 1313 s->sect = sect; 1314 s->type = SRODATA; 1315 s->value = datsize - sect->vaddr; 1316 growdatsize(&datsize, s); 1317 } 1318 sect->len = datsize - sect->vaddr; 1319 1320 /* gopclntab */ 1321 sect = addsection(segro, ".gopclntab", 04); 1322 sect->align = maxalign(s, SELFROSECT-1); 1323 datsize = rnd(datsize, sect->align); 1324 sect->vaddr = datsize; 1325 lookup("pclntab", 0)->sect = sect; 1326 lookup("epclntab", 0)->sect = sect; 1327 for(; s != nil && s->type < SELFROSECT; s = s->next) { 1328 datsize = aligndatsize(datsize, s); 1329 s->sect = sect; 1330 s->type = SRODATA; 1331 s->value = datsize - sect->vaddr; 1332 growdatsize(&datsize, s); 1333 } 1334 sect->len = datsize - sect->vaddr; 1335 1336 /* read-only ELF, Mach-O sections */ 1337 for(; s != nil && s->type < SELFSECT; s = s->next) { 1338 sect = addsection(segro, s->name, 04); 1339 sect->align = symalign(s); 1340 datsize = rnd(datsize, sect->align); 1341 sect->vaddr = datsize; 1342 s->sect = sect; 1343 s->type = SRODATA; 1344 s->value = datsize - sect->vaddr; 1345 growdatsize(&datsize, s); 1346 sect->len = datsize - sect->vaddr; 1347 } 1348 1349 // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. 1350 if(datsize != (uint32)datsize) { 1351 diag("read-only data segment too large"); 1352 } 1353 1354 /* number the sections */ 1355 n = 1; 1356 for(sect = segtext.sect; sect != nil; sect = sect->next) 1357 sect->extnum = n++; 1358 for(sect = segrodata.sect; sect != nil; sect = sect->next) 1359 sect->extnum = n++; 1360 for(sect = segdata.sect; sect != nil; sect = sect->next) 1361 sect->extnum = n++; 1362 } 1363 1364 // assign addresses to text 1365 void 1366 textaddress(void) 1367 { 1368 uvlong va; 1369 Prog *p; 1370 Section *sect; 1371 Sym *sym, *sub; 1372 1373 addsection(&segtext, ".text", 05); 1374 1375 // Assign PCs in text segment. 1376 // Could parallelize, by assigning to text 1377 // and then letting threads copy down, but probably not worth it. 1378 sect = segtext.sect; 1379 sect->align = FuncAlign; 1380 lookup("text", 0)->sect = sect; 1381 lookup("etext", 0)->sect = sect; 1382 va = INITTEXT; 1383 sect->vaddr = va; 1384 for(sym = textp; sym != nil; sym = sym->next) { 1385 sym->sect = sect; 1386 if(sym->type & SSUB) 1387 continue; 1388 if(sym->align != 0) 1389 va = rnd(va, sym->align); 1390 else if(sym->text != P) 1391 va = rnd(va, FuncAlign); 1392 sym->value = 0; 1393 for(sub = sym; sub != S; sub = sub->sub) { 1394 sub->value += va; 1395 for(p = sub->text; p != P; p = p->link) 1396 p->pc += sub->value; 1397 } 1398 if(sym->size == 0 && sym->sub != S) { 1399 cursym = sym; 1400 } 1401 va += sym->size; 1402 } 1403 sect->len = va - sect->vaddr; 1404 } 1405 1406 // assign addresses 1407 void 1408 address(void) 1409 { 1410 Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss; 1411 Section *typelink; 1412 Sym *sym, *sub; 1413 uvlong va; 1414 vlong vlen; 1415 1416 va = INITTEXT; 1417 segtext.rwx = 05; 1418 segtext.vaddr = va; 1419 segtext.fileoff = HEADR; 1420 for(s=segtext.sect; s != nil; s=s->next) { 1421 //print("%s at %#llux + %#llux\n", s->name, va, (vlong)s->len); 1422 va = rnd(va, s->align); 1423 s->vaddr = va; 1424 va += s->len; 1425 } 1426 segtext.len = va - INITTEXT; 1427 segtext.filelen = segtext.len; 1428 1429 if(segrodata.sect != nil) { 1430 // align to page boundary so as not to mix 1431 // rodata and executable text. 1432 va = rnd(va, INITRND); 1433 1434 segrodata.rwx = 04; 1435 segrodata.vaddr = va; 1436 segrodata.fileoff = va - segtext.vaddr + segtext.fileoff; 1437 segrodata.filelen = 0; 1438 for(s=segrodata.sect; s != nil; s=s->next) { 1439 va = rnd(va, s->align); 1440 s->vaddr = va; 1441 va += s->len; 1442 } 1443 segrodata.len = va - segrodata.vaddr; 1444 segrodata.filelen = segrodata.len; 1445 } 1446 1447 va = rnd(va, INITRND); 1448 segdata.rwx = 06; 1449 segdata.vaddr = va; 1450 segdata.fileoff = va - segtext.vaddr + segtext.fileoff; 1451 segdata.filelen = 0; 1452 if(HEADTYPE == Hwindows) 1453 segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN); 1454 if(HEADTYPE == Hplan9x64 || HEADTYPE == Hplan9x32) 1455 segdata.fileoff = segtext.fileoff + segtext.filelen; 1456 data = nil; 1457 noptr = nil; 1458 bss = nil; 1459 noptrbss = nil; 1460 for(s=segdata.sect; s != nil; s=s->next) { 1461 vlen = s->len; 1462 if(s->next) 1463 vlen = s->next->vaddr - s->vaddr; 1464 s->vaddr = va; 1465 va += vlen; 1466 segdata.len = va - segdata.vaddr; 1467 if(strcmp(s->name, ".data") == 0) 1468 data = s; 1469 if(strcmp(s->name, ".noptrdata") == 0) 1470 noptr = s; 1471 if(strcmp(s->name, ".bss") == 0) 1472 bss = s; 1473 if(strcmp(s->name, ".noptrbss") == 0) 1474 noptrbss = s; 1475 } 1476 segdata.filelen = bss->vaddr - segdata.vaddr; 1477 1478 text = segtext.sect; 1479 if(segrodata.sect) 1480 rodata = segrodata.sect; 1481 else 1482 rodata = text->next; 1483 typelink = rodata->next; 1484 symtab = typelink->next; 1485 pclntab = symtab->next; 1486 1487 for(sym = datap; sym != nil; sym = sym->next) { 1488 cursym = sym; 1489 sym->value += sym->sect->vaddr; 1490 for(sub = sym->sub; sub != nil; sub = sub->sub) 1491 sub->value += sym->value; 1492 } 1493 1494 xdefine("text", STEXT, text->vaddr); 1495 xdefine("etext", STEXT, text->vaddr + text->len); 1496 xdefine("rodata", SRODATA, rodata->vaddr); 1497 xdefine("erodata", SRODATA, rodata->vaddr + rodata->len); 1498 xdefine("typelink", SRODATA, typelink->vaddr); 1499 xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len); 1500 1501 sym = lookup("gcdata", 0); 1502 xdefine("egcdata", SRODATA, symaddr(sym) + sym->size); 1503 lookup("egcdata", 0)->sect = sym->sect; 1504 1505 sym = lookup("gcbss", 0); 1506 xdefine("egcbss", SRODATA, symaddr(sym) + sym->size); 1507 lookup("egcbss", 0)->sect = sym->sect; 1508 1509 xdefine("symtab", SRODATA, symtab->vaddr); 1510 xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len); 1511 xdefine("pclntab", SRODATA, pclntab->vaddr); 1512 xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len); 1513 xdefine("noptrdata", SNOPTRDATA, noptr->vaddr); 1514 xdefine("enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len); 1515 xdefine("bss", SBSS, bss->vaddr); 1516 xdefine("ebss", SBSS, bss->vaddr + bss->len); 1517 xdefine("data", SDATA, data->vaddr); 1518 xdefine("edata", SDATA, data->vaddr + data->len); 1519 xdefine("noptrbss", SNOPTRBSS, noptrbss->vaddr); 1520 xdefine("enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len); 1521 xdefine("end", SBSS, segdata.vaddr + segdata.len); 1522 }