Changeset 628
- Timestamp:
- 08/26/10 06:12:38 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/elfobj.c (modified) (6 diffs)
- trunk/src/backend/elfobj.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/elfobj.c
r589 r628 20 20 #include <alloca.h> 21 21 #endif 22 22 23 23 #include "cc.h" 24 24 #include "global.h" 25 25 #include "code.h" 26 26 #include "type.h" 27 27 #include "melf.h" 28 28 #include "outbuf.h" 29 29 #include "filespec.h" 30 30 #include "cv4.h" 31 31 #include "cgcv.h" 32 32 #include "dt.h" 33 33 34 34 #include "aa.h" 35 35 #include "tinfo.h" 36 36 37 37 #if ELFOBJ 38 38 39 39 #include "dwarf.h" 40 41 #include "aa.h" 42 #include "tinfo.h" 40 43 41 44 //#define DEBSYM 0x7E 42 45 43 46 static Outbuffer *fobjbuf; 44 47 45 48 regm_t BYTEREGS = BYTEREGS_INIT; 46 49 regm_t ALLREGS = ALLREGS_INIT; 47 50 48 51 static char __file__[] = __FILE__; // for tassert.h 49 52 #include "tassert.h" 50 53 51 54 #define MATCH_SECTION 1 52 55 53 56 #define DEST_LEN (IDMAX + IDOHD + 1) 54 57 char *obj_mangle2(Symbol *s,char *dest); 55 58 56 59 #if MARS 57 60 // C++ name mangling is handled by front end 58 61 #define cpp_mangle(s) ((s)->Sident) 59 62 #endif … … 106 109 static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz, 107 110 unsigned typ,unsigned bind,IDXSEC sec); 108 111 static long elf_align(FILE *fd, targ_size_t size, long offset); 109 112 110 113 // The object file is built is several separate pieces 111 114 112 115 // Non-repeatable section types have single output buffers 113 116 // Pre-allocated buffers are defined for: 114 117 // Section Names string table 115 118 // Section Headers table 116 119 // Symbol table 117 120 // String table 118 121 // Notes section 119 122 // Comment data 120 123 121 124 // Section Names - String table for section names only 122 125 static Outbuffer *section_names; 123 126 #define SEC_NAMES_INIT 800 124 127 #define SEC_NAMES_INC 400 125 128 129 // Hash table for section_names 130 AArray *section_names_hashtable; 131 132 /* ====================== Cached Strings in section_names ================= */ 133 134 struct TypeInfo_Idxstr : TypeInfo 135 { 136 const char* toString(); 137 hash_t getHash(void *p); 138 int equals(void *p1, void *p2); 139 int compare(void *p1, void *p2); 140 size_t tsize(); 141 void swap(void *p1, void *p2); 142 }; 143 144 TypeInfo_Idxstr ti_idxstr; 145 146 const char* TypeInfo_Idxstr::toString() 147 { 148 return "IDXSTR"; 149 } 150 151 hash_t TypeInfo_Idxstr::getHash(void *p) 152 { 153 IDXSTR a = *(IDXSTR *)p; 154 hash_t hash = 0; 155 for (const char *s = (char *)(section_names->buf + a); 156 *s; 157 s++) 158 { 159 hash = hash * 11 + *s; 160 } 161 return hash; 162 } 163 164 int TypeInfo_Idxstr::equals(void *p1, void *p2) 165 { 166 IDXSTR a1 = *(IDXSTR*)p1; 167 IDXSTR a2 = *(IDXSTR*)p2; 168 const char *s1 = (char *)(section_names->buf + a1); 169 const char *s2 = (char *)(section_names->buf + a2); 170 171 return strcmp(s1, s2) == 0; 172 } 173 174 int TypeInfo_Idxstr::compare(void *p1, void *p2) 175 { 176 IDXSTR a1 = *(IDXSTR*)p1; 177 IDXSTR a2 = *(IDXSTR*)p2; 178 const char *s1 = (char *)(section_names->buf + a1); 179 const char *s2 = (char *)(section_names->buf + a2); 180 181 return strcmp(s1, s2); 182 } 183 184 size_t TypeInfo_Idxstr::tsize() 185 { 186 return sizeof(IDXSTR); 187 } 188 189 void TypeInfo_Idxstr::swap(void *p1, void *p2) 190 { 191 assert(0); 192 } 193 194 195 /* ======================================================================== */ 196 126 197 // String Table - String table for all other names 127 198 static Outbuffer *symtab_strings; 128 199 129 200 130 201 // Section Headers 131 202 Outbuffer *SECbuf; // Buffer to build section table in 132 203 #define SecHdrTab ((Elf32_Shdr *)SECbuf->buf) 133 204 #define GET_SECTION(secidx) (SecHdrTab + secidx) 134 205 #define GET_SECTION_NAME(secidx) (section_names->buf + SecHdrTab[secidx].sh_name) 135 206 136 207 // The relocation for text and data seems to get lost. 137 208 // Try matching the order gcc output them 138 209 // This means defining the sections and then removing them if they are 139 210 // not used. 140 211 static int section_cnt; // Number of sections in table 141 212 142 213 #define SHI_TEXT 1 143 214 #define SHI_RELTEXT 2 144 215 #define SHI_DATA 3 145 216 #define SHI_RELDATA 4 … … 236 307 IDXSTR elf_addstr(Outbuffer *strtab, const char *str) 237 308 { 238 309 //dbg_printf("elf_addstr(strtab = x%x str = '%s')\n",strtab,str); 239 310 IDXSTR idx = strtab->size(); // remember starting offset 240 311 strtab->writeString(str); 241 312 //dbg_printf("\tidx %d, new size %d\n",idx,strtab->size()); 242 313 return idx; 243 314 } 244 315 245 316 /******************************* 246 317 * Find a string in a string table 247 318 * Input: 248 319 * strtab = string table for entry 249 320 * str = string to find 250 321 * 251 322 * Returns index into the specified string table or 0. 252 323 */ 253 324 254 325 static IDXSTR elf_findstr(Outbuffer *strtab, const char *str, const char *suffix) 255 326 { 327 //printf("elf_findstr(strtab = %p, str = %s, suffix = %s\n", strtab, str ? str : "", suffix ? suffix : ""); 328 329 size_t len = strlen(str); 330 331 // Combine str~suffix and have buf point to the combination 332 #ifdef DEBUG 333 char tmpbuf[25]; // to exercise the alloca() code path 334 #else 335 char tmpbuf[1024]; // the alloca() code path is slow 336 #endif 337 const char *buf; 338 if (suffix) 339 { 340 size_t suffixlen = strlen(suffix); 341 if (len + suffixlen >= sizeof(tmpbuf)) 342 { 343 buf = (char *)alloca(len + suffixlen + 1); 344 assert(buf); 345 } 346 else 347 { 348 buf = tmpbuf; 349 } 350 memcpy((char *)buf, str, len); 351 memcpy((char *)buf + len, suffix, suffixlen + 1); 352 len += suffixlen; 353 } 354 else 355 buf = str; 356 357 // Linear search, slow 256 358 const char *ent = (char *)strtab->buf+1; 257 359 const char *pend = ent+strtab->size() - 1; 258 const char *s = str; 259 const char *sx = suffix; 260 int len = strlen(str); 261 262 if (suffix) 263 len += strlen(suffix); 264 265 while(ent < pend) 266 { 267 if(*ent == 0) // end of table entry 268 { 269 if(*s == 0 && !sx) // end of string - found a match 270 { 271 return ent - (const char *)strtab->buf - len; 272 } 273 else // table entry too short 274 { 275 s = str; // back to beginning of string 276 sx = suffix; 277 ent++; // start of next table entry 278 } 279 } 280 else if (*s == 0 && sx && *sx == *ent) 281 { // matched first string 282 s = sx+1; // switch to suffix 283 ent++; 284 sx = NULL; 285 } 286 else // continue comparing 287 { 288 if (*ent == *s) 289 { // Have a match going 290 ent++; 291 s++; 292 } 293 else // no match 294 { 295 while(*ent != 0) // skip to end of entry 296 ent++; 297 ent++; // start of next table entry 298 s = str; // back to beginning of string 299 sx = suffix; 300 } 301 } 360 while (ent + len < pend) 361 { 362 if (memcmp(buf, ent, len + 1) == 0) 363 return ent - (const char *)strtab->buf; 364 ent = (const char *)memchr(ent, 0, pend - ent); 365 ent += 1; 302 366 } 303 367 return 0; // never found match 304 368 } 305 369 306 370 /******************************* 307 371 * Output a mangled string into the symbol string table 308 372 * Input: 309 373 * str = string to add 310 374 * 311 375 * Returns index into the table. 312 376 */ 313 377 314 378 static IDXSTR elf_addmangled(Symbol *s) 315 379 { 316 380 //printf("elf_addmangled(%s)\n", s->Sident); 317 381 char dest[DEST_LEN]; 318 382 char *destr; 319 383 const char *name; 320 384 int len; 321 385 IDXSTR namidx; … … 450 514 sec.sh_flags = flags; 451 515 sec.sh_addr = addr; 452 516 sec.sh_offset = offset; 453 517 sec.sh_size = size; 454 518 sec.sh_link = link; 455 519 sec.sh_info = info; 456 520 sec.sh_addralign = addralign; 457 521 sec.sh_entsize = entsize; 458 522 459 523 if (!SECbuf) 460 524 { SECbuf = new Outbuffer(4 * sizeof(Elf32_Shdr)); 461 525 SECbuf->reserve(16 * sizeof(Elf32_Shdr)); 462 526 } 463 527 SECbuf->write((void *)&sec, sizeof(sec)); 464 528 return section_cnt++; 465 529 } 466 530 467 531 static IDXSEC elf_newsection(const char *name, const char *suffix, 468 532 elf_u32_f32 type, elf_u32_f32 flags) 469 533 { 470 Elf32_Shdr sec; 471 472 // dbg_printf("elf_newsection(%s,%s,type %d, flags x%x)\n", 473 // name?name:"",suffix?suffix:"",type,flags); 474 475 #if 1 476 int namidx = elf_addstr(section_names,name); 477 #else 478 int namidx = section_names->size(); 534 // dbg_printf("elf_newsection(%s,%s,type %d, flags x%x)\n", 535 // name?name:"",suffix?suffix:"",type,flags); 536 537 IDXSTR namidx = section_names->size(); 479 538 section_names->writeString(name); 480 #endif 481 // name in section names table 482 if (suffix) // suffix - back up over NUL and 483 { // append suffix string 484 section_names->setsize(section_names->size()-1); 539 if (suffix) 540 { // Append suffix string 541 section_names->setsize(section_names->size() - 1); // back up over terminating 0 485 542 section_names->writeString(suffix); 486 }; 543 } 544 IDXSTR *pidx = (IDXSTR *)section_names_hashtable->get(&namidx); 545 assert(!*pidx); // must not already exist 546 *pidx = namidx; 547 487 548 return elf_newsection2(namidx,type,flags,0,0,0,0,0,0,0); 488 549 } 489 550 490 551 /************************** 491 552 * Ouput read only data and generate a symbol for it. 492 553 * 493 554 */ 494 555 495 556 symbol *elf_sym_cdata(tym_t ty,char *p,int len) 496 557 { 497 558 symbol *s; 498 559 499 560 #if 0 500 561 if (OPT_IS_SET(OPTfwritable_strings)) 501 562 { 502 563 alignOffset(DATA, tysize(ty)); 503 564 s = symboldata(Doffset, ty); 504 565 SegData[DATA]->SDbuf->write(p,len); 505 566 s->Sseg = DATA; 506 567 s->Soffset = Doffset; // Remember its offset into DATA section … … 597 658 #define NAMIDX_STRTAB 9 // .strtab 598 659 #define NAMIDX_SHSTRTAB 17 // .shstrtab 599 660 #define NAMIDX_TEXT 27 // .text 600 661 #define NAMIDX_DATA 33 // .data 601 662 #define NAMIDX_BSS 39 // .bss 602 663 #define NAMIDX_NOTE 44 // .note 603 664 #define NAMIDX_COMMENT 50 // .comment 604 665 #define NAMIDX_RODATA 59 // .rodata 605 666 #define NAMIDX_RELTEXT 67 // .rel.text and .rela.text 606 667 #define NAMIDX_RELDATA 77 // .rel.data 607 668 #define NAMIDX_RELDATA64 78 // .rela.data 608 669 609 670 if (section_names) 610 671 section_names->setsize(sizeof(section_names_init64)); 611 672 else 612 673 { section_names = new Outbuffer(512); 613 674 section_names->reserve(1024); 614 675 section_names->writen(section_names_init64, sizeof(section_names_init64)); 615 676 } 616 677 678 if (section_names_hashtable) 679 delete section_names_hashtable; 680 section_names_hashtable = new AArray(&ti_idxstr, sizeof(IDXSTR)); 681 617 682 // name,type,flags,addr,offset,size,link,info,addralign,entsize 618 683 elf_newsection2(0, SHT_NULL, 0, 0,0,0,0,0, 0,0); 619 684 elf_newsection2(NAMIDX_TEXT,SHT_PROGDEF,SHF_ALLOC|SHF_EXECINSTR,0,0,0,0,0, 4,0); 620 685 elf_newsection2(NAMIDX_RELTEXT,SHT_RELA, 0,0,0,0,SHI_SYMTAB, SHI_TEXT, 8,8); 621 686 elf_newsection2(NAMIDX_DATA,SHT_PROGDEF,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 8,0); 622 687 elf_newsection2(NAMIDX_RELDATA64,SHT_RELA, 0,0,0,0,SHI_SYMTAB, SHI_DATA, 8,8); 623 688 elf_newsection2(NAMIDX_BSS, SHT_NOBITS,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 16,0); 624 689 elf_newsection2(NAMIDX_RODATA,SHT_PROGDEF,SHF_ALLOC, 0,0,0,0,0, 1,0); 625 690 elf_newsection2(NAMIDX_STRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 626 691 elf_newsection2(NAMIDX_SYMTAB,SHT_SYMTAB, 0, 0,0,0,0,0, 8,0); 627 692 elf_newsection2(NAMIDX_SHSTRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 628 693 elf_newsection2(NAMIDX_COMMENT, SHT_PROGDEF,0, 0,0,0,0,0, 1,0); 629 694 elf_newsection2(NAMIDX_NOTE,SHT_NOTE, 0, 0,0,0,0,0, 1,0); 695 696 IDXSTR namidx; 697 namidx = NAMIDX_TEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 698 namidx = NAMIDX_RELTEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 699 namidx = NAMIDX_DATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 700 namidx = NAMIDX_RELDATA64; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 701 namidx = NAMIDX_BSS; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 702 namidx = NAMIDX_RODATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 703 namidx = NAMIDX_STRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 704 namidx = NAMIDX_SYMTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 705 namidx = NAMIDX_SHSTRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 706 namidx = NAMIDX_COMMENT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 707 namidx = NAMIDX_NOTE; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 630 708 } 631 709 else 632 710 { 633 711 static char section_names_init[] = 634 712 "\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.bss\0.note\0.comment\0.rodata\0.rel.text\0.rel.data"; 635 713 636 714 if (section_names) 637 715 section_names->setsize(sizeof(section_names_init)); 638 716 else 639 717 { section_names = new Outbuffer(512); 640 section_names->reserve(10 24);718 section_names->reserve(100*1024); 641 719 section_names->writen(section_names_init, sizeof(section_names_init)); 642 720 } 721 722 if (section_names_hashtable) 723 delete section_names_hashtable; 724 section_names_hashtable = new AArray(&ti_idxstr, sizeof(IDXSTR)); 643 725 644 726 // name,type,flags,addr,offset,size,link,info,addralign,entsize 645 727 elf_newsection2(0, SHT_NULL, 0, 0,0,0,0,0, 0,0); 646 728 elf_newsection2(NAMIDX_TEXT,SHT_PROGDEF,SHF_ALLOC|SHF_EXECINSTR,0,0,0,0,0, 16,0); 647 729 elf_newsection2(NAMIDX_RELTEXT,SHT_REL, 0,0,0,0,SHI_SYMTAB, SHI_TEXT, 4,8); 648 730 elf_newsection2(NAMIDX_DATA,SHT_PROGDEF,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 4,0); 649 731 elf_newsection2(NAMIDX_RELDATA,SHT_REL, 0,0,0,0,SHI_SYMTAB, SHI_DATA, 4,8); 650 732 elf_newsection2(NAMIDX_BSS, SHT_NOBITS,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 32,0); 651 733 elf_newsection2(NAMIDX_RODATA,SHT_PROGDEF,SHF_ALLOC, 0,0,0,0,0, 1,0); 652 734 elf_newsection2(NAMIDX_STRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 653 735 elf_newsection2(NAMIDX_SYMTAB,SHT_SYMTAB, 0, 0,0,0,0,0, 4,0); 654 736 elf_newsection2(NAMIDX_SHSTRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 655 737 elf_newsection2(NAMIDX_COMMENT, SHT_PROGDEF,0, 0,0,0,0,0, 1,0); 656 738 elf_newsection2(NAMIDX_NOTE,SHT_NOTE, 0, 0,0,0,0,0, 1,0); 739 740 IDXSTR namidx; 741 namidx = NAMIDX_TEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 742 namidx = NAMIDX_RELTEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 743 namidx = NAMIDX_DATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 744 namidx = NAMIDX_RELDATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 745 namidx = NAMIDX_BSS; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 746 namidx = NAMIDX_RODATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 747 namidx = NAMIDX_STRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 748 namidx = NAMIDX_SYMTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 749 namidx = NAMIDX_SHSTRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 750 namidx = NAMIDX_COMMENT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 751 namidx = NAMIDX_NOTE; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 657 752 } 658 753 659 754 if (SYMbuf) 660 755 SYMbuf->setsize(0); 661 756 symbol_idx = 0; 662 757 local_cnt = 0; 663 758 // The symbols that every object file has 664 759 elf_addsym(0, 0, 0, STT_NOTYPE, STB_LOCAL, 0); 665 760 elf_addsym(0, 0, 0, STT_FILE, STB_LOCAL, SHT_ABS); // STI_FILE 666 761 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_TEXT); // STI_TEXT 667 762 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_DATA); // STI_DATA 668 763 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_BSS); // STI_BSS 669 764 elf_addsym(0, 0, 0, STT_NOTYPE, STB_LOCAL, SHI_TEXT); // STI_GCC 670 765 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_RODAT); // STI_RODAT 671 766 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_NOTE); // STI_NOTE 672 767 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_COM); // STI_COM 673 768 674 769 // Initialize output buffers for CODE, DATA and COMMENTS 675 770 // (NOTE not supported, BSS not required) 676 771 … … 1539 1634 pseg->SDbuf->reserve(1024); 1540 1635 } 1541 1636 } 1542 1637 if (pseg->SDrel) 1543 1638 pseg->SDrel->setsize(0); 1544 1639 pseg->SDsymidx = symidx; 1545 1640 pseg->SDrelidx = relidx; 1546 1641 pseg->SDrelmaxoff = 0; 1547 1642 pseg->SDrelindex = 0; 1548 1643 pseg->SDrelcnt = 0; 1549 1644 pseg->SDshtidxout = 0; 1550 1645 pseg->SDsym = NULL; 1551 1646 return seg; 1552 1647 } 1553 1648 1554 1649 int elf_getsegment(const char *name, const char *suffix, int type, int flags, 1555 1650 int align) 1556 1651 { 1557 1652 //printf("elf_getsegment(%s,%s,flags %x, align %d)\n",name,suffix,flags,align); 1558 1653 1559 IDXSTR namidx; 1560 if (namidx = elf_findstr(section_names,name,suffix)) 1561 { // this section name exists 1654 // Add name~suffix to the section_names table 1655 IDXSTR namidx = section_names->size(); 1656 section_names->writeString(name); 1657 if (suffix) 1658 { // Append suffix string 1659 section_names->setsize(section_names->size() - 1); // back up over terminating 0 1660 section_names->writeString(suffix); 1661 } 1662 IDXSTR *pidx = (IDXSTR *)section_names_hashtable->get(&namidx); 1663 if (*pidx) 1664 { // this section name already exists 1665 section_names->setsize(namidx); // remove addition 1666 namidx = *pidx; 1562 1667 for (int seg = CODE; seg <= seg_count; seg++) 1563 1668 { // should be in segment table 1564 1669 if (MAP_SEG2SEC(seg)->sh_name == namidx) 1565 1670 { 1566 1671 return seg; // found section for segment 1567 1672 } 1568 1673 } 1569 1674 assert(0); // but it's not a segment 1570 1675 // FIX - should be an error message conflict with section names 1571 1676 } 1677 *pidx = namidx; 1572 1678 1573 1679 //dbg_printf("\tNew segment - %d size %d\n", seg,SegData[seg]->SDbuf); 1574 IDXSEC shtidx = elf_newsection (name,suffix,type,flags);1680 IDXSEC shtidx = elf_newsection2(namidx,type,flags,0,0,0,0,0,0,0); 1575 1681 SecHdrTab[shtidx].sh_addralign = align; 1576 1682 IDXSYM symidx = elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, shtidx); 1577 1683 int seg = elf_getsegment2(shtidx, symidx, 0); 1578 1684 //printf("-elf_getsegment() = %d\n", seg); 1579 1685 return seg; 1580 1686 } 1581 1687 1582 1688 /******************************** 1583 1689 * Define a new code segment. 1584 1690 * Input: 1585 1691 * name name of segment, if NULL then revert to default 1586 1692 * suffix 0 use name as is 1587 1693 * 1 append "_TEXT" to name 1588 1694 * Output: 1589 1695 * cseg segment index of new current code segment 1590 1696 * Coffset starting offset in cseg 1591 1697 * Returns: 1592 1698 * segment index of newly created code segment 1593 1699 */ 1594 1700 trunk/src/backend/elfobj.c
r589 r628 20 20 #include <alloca.h> 21 21 #endif 22 22 23 23 #include "cc.h" 24 24 #include "global.h" 25 25 #include "code.h" 26 26 #include "type.h" 27 27 #include "melf.h" 28 28 #include "outbuf.h" 29 29 #include "filespec.h" 30 30 #include "cv4.h" 31 31 #include "cgcv.h" 32 32 #include "dt.h" 33 33 34 34 #include "aa.h" 35 35 #include "tinfo.h" 36 36 37 37 #if ELFOBJ 38 38 39 39 #include "dwarf.h" 40 41 #include "aa.h" 42 #include "tinfo.h" 40 43 41 44 //#define DEBSYM 0x7E 42 45 43 46 static Outbuffer *fobjbuf; 44 47 45 48 regm_t BYTEREGS = BYTEREGS_INIT; 46 49 regm_t ALLREGS = ALLREGS_INIT; 47 50 48 51 static char __file__[] = __FILE__; // for tassert.h 49 52 #include "tassert.h" 50 53 51 54 #define MATCH_SECTION 1 52 55 53 56 #define DEST_LEN (IDMAX + IDOHD + 1) 54 57 char *obj_mangle2(Symbol *s,char *dest); 55 58 56 59 #if MARS 57 60 // C++ name mangling is handled by front end 58 61 #define cpp_mangle(s) ((s)->Sident) 59 62 #endif … … 106 109 static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz, 107 110 unsigned typ,unsigned bind,IDXSEC sec); 108 111 static long elf_align(FILE *fd, targ_size_t size, long offset); 109 112 110 113 // The object file is built is several separate pieces 111 114 112 115 // Non-repeatable section types have single output buffers 113 116 // Pre-allocated buffers are defined for: 114 117 // Section Names string table 115 118 // Section Headers table 116 119 // Symbol table 117 120 // String table 118 121 // Notes section 119 122 // Comment data 120 123 121 124 // Section Names - String table for section names only 122 125 static Outbuffer *section_names; 123 126 #define SEC_NAMES_INIT 800 124 127 #define SEC_NAMES_INC 400 125 128 129 // Hash table for section_names 130 AArray *section_names_hashtable; 131 132 /* ====================== Cached Strings in section_names ================= */ 133 134 struct TypeInfo_Idxstr : TypeInfo 135 { 136 const char* toString(); 137 hash_t getHash(void *p); 138 int equals(void *p1, void *p2); 139 int compare(void *p1, void *p2); 140 size_t tsize(); 141 void swap(void *p1, void *p2); 142 }; 143 144 TypeInfo_Idxstr ti_idxstr; 145 146 const char* TypeInfo_Idxstr::toString() 147 { 148 return "IDXSTR"; 149 } 150 151 hash_t TypeInfo_Idxstr::getHash(void *p) 152 { 153 IDXSTR a = *(IDXSTR *)p; 154 hash_t hash = 0; 155 for (const char *s = (char *)(section_names->buf + a); 156 *s; 157 s++) 158 { 159 hash = hash * 11 + *s; 160 } 161 return hash; 162 } 163 164 int TypeInfo_Idxstr::equals(void *p1, void *p2) 165 { 166 IDXSTR a1 = *(IDXSTR*)p1; 167 IDXSTR a2 = *(IDXSTR*)p2; 168 const char *s1 = (char *)(section_names->buf + a1); 169 const char *s2 = (char *)(section_names->buf + a2); 170 171 return strcmp(s1, s2) == 0; 172 } 173 174 int TypeInfo_Idxstr::compare(void *p1, void *p2) 175 { 176 IDXSTR a1 = *(IDXSTR*)p1; 177 IDXSTR a2 = *(IDXSTR*)p2; 178 const char *s1 = (char *)(section_names->buf + a1); 179 const char *s2 = (char *)(section_names->buf + a2); 180 181 return strcmp(s1, s2); 182 } 183 184 size_t TypeInfo_Idxstr::tsize() 185 { 186 return sizeof(IDXSTR); 187 } 188 189 void TypeInfo_Idxstr::swap(void *p1, void *p2) 190 { 191 assert(0); 192 } 193 194 195 /* ======================================================================== */ 196 126 197 // String Table - String table for all other names 127 198 static Outbuffer *symtab_strings; 128 199 129 200 130 201 // Section Headers 131 202 Outbuffer *SECbuf; // Buffer to build section table in 132 203 #define SecHdrTab ((Elf32_Shdr *)SECbuf->buf) 133 204 #define GET_SECTION(secidx) (SecHdrTab + secidx) 134 205 #define GET_SECTION_NAME(secidx) (section_names->buf + SecHdrTab[secidx].sh_name) 135 206 136 207 // The relocation for text and data seems to get lost. 137 208 // Try matching the order gcc output them 138 209 // This means defining the sections and then removing them if they are 139 210 // not used. 140 211 static int section_cnt; // Number of sections in table 141 212 142 213 #define SHI_TEXT 1 143 214 #define SHI_RELTEXT 2 144 215 #define SHI_DATA 3 145 216 #define SHI_RELDATA 4 … … 236 307 IDXSTR elf_addstr(Outbuffer *strtab, const char *str) 237 308 { 238 309 //dbg_printf("elf_addstr(strtab = x%x str = '%s')\n",strtab,str); 239 310 IDXSTR idx = strtab->size(); // remember starting offset 240 311 strtab->writeString(str); 241 312 //dbg_printf("\tidx %d, new size %d\n",idx,strtab->size()); 242 313 return idx; 243 314 } 244 315 245 316 /******************************* 246 317 * Find a string in a string table 247 318 * Input: 248 319 * strtab = string table for entry 249 320 * str = string to find 250 321 * 251 322 * Returns index into the specified string table or 0. 252 323 */ 253 324 254 325 static IDXSTR elf_findstr(Outbuffer *strtab, const char *str, const char *suffix) 255 326 { 327 //printf("elf_findstr(strtab = %p, str = %s, suffix = %s\n", strtab, str ? str : "", suffix ? suffix : ""); 328 329 size_t len = strlen(str); 330 331 // Combine str~suffix and have buf point to the combination 332 #ifdef DEBUG 333 char tmpbuf[25]; // to exercise the alloca() code path 334 #else 335 char tmpbuf[1024]; // the alloca() code path is slow 336 #endif 337 const char *buf; 338 if (suffix) 339 { 340 size_t suffixlen = strlen(suffix); 341 if (len + suffixlen >= sizeof(tmpbuf)) 342 { 343 buf = (char *)alloca(len + suffixlen + 1); 344 assert(buf); 345 } 346 else 347 { 348 buf = tmpbuf; 349 } 350 memcpy((char *)buf, str, len); 351 memcpy((char *)buf + len, suffix, suffixlen + 1); 352 len += suffixlen; 353 } 354 else 355 buf = str; 356 357 // Linear search, slow 256 358 const char *ent = (char *)strtab->buf+1; 257 359 const char *pend = ent+strtab->size() - 1; 258 const char *s = str; 259 const char *sx = suffix; 260 int len = strlen(str); 261 262 if (suffix) 263 len += strlen(suffix); 264 265 while(ent < pend) 266 { 267 if(*ent == 0) // end of table entry 268 { 269 if(*s == 0 && !sx) // end of string - found a match 270 { 271 return ent - (const char *)strtab->buf - len; 272 } 273 else // table entry too short 274 { 275 s = str; // back to beginning of string 276 sx = suffix; 277 ent++; // start of next table entry 278 } 279 } 280 else if (*s == 0 && sx && *sx == *ent) 281 { // matched first string 282 s = sx+1; // switch to suffix 283 ent++; 284 sx = NULL; 285 } 286 else // continue comparing 287 { 288 if (*ent == *s) 289 { // Have a match going 290 ent++; 291 s++; 292 } 293 else // no match 294 { 295 while(*ent != 0) // skip to end of entry 296 ent++; 297 ent++; // start of next table entry 298 s = str; // back to beginning of string 299 sx = suffix; 300 } 301 } 360 while (ent + len < pend) 361 { 362 if (memcmp(buf, ent, len + 1) == 0) 363 return ent - (const char *)strtab->buf; 364 ent = (const char *)memchr(ent, 0, pend - ent); 365 ent += 1; 302 366 } 303 367 return 0; // never found match 304 368 } 305 369 306 370 /******************************* 307 371 * Output a mangled string into the symbol string table 308 372 * Input: 309 373 * str = string to add 310 374 * 311 375 * Returns index into the table. 312 376 */ 313 377 314 378 static IDXSTR elf_addmangled(Symbol *s) 315 379 { 316 380 //printf("elf_addmangled(%s)\n", s->Sident); 317 381 char dest[DEST_LEN]; 318 382 char *destr; 319 383 const char *name; 320 384 int len; 321 385 IDXSTR namidx; … … 450 514 sec.sh_flags = flags; 451 515 sec.sh_addr = addr; 452 516 sec.sh_offset = offset; 453 517 sec.sh_size = size; 454 518 sec.sh_link = link; 455 519 sec.sh_info = info; 456 520 sec.sh_addralign = addralign; 457 521 sec.sh_entsize = entsize; 458 522 459 523 if (!SECbuf) 460 524 { SECbuf = new Outbuffer(4 * sizeof(Elf32_Shdr)); 461 525 SECbuf->reserve(16 * sizeof(Elf32_Shdr)); 462 526 } 463 527 SECbuf->write((void *)&sec, sizeof(sec)); 464 528 return section_cnt++; 465 529 } 466 530 467 531 static IDXSEC elf_newsection(const char *name, const char *suffix, 468 532 elf_u32_f32 type, elf_u32_f32 flags) 469 533 { 470 Elf32_Shdr sec; 471 472 // dbg_printf("elf_newsection(%s,%s,type %d, flags x%x)\n", 473 // name?name:"",suffix?suffix:"",type,flags); 474 475 #if 1 476 int namidx = elf_addstr(section_names,name); 477 #else 478 int namidx = section_names->size(); 534 // dbg_printf("elf_newsection(%s,%s,type %d, flags x%x)\n", 535 // name?name:"",suffix?suffix:"",type,flags); 536 537 IDXSTR namidx = section_names->size(); 479 538 section_names->writeString(name); 480 #endif 481 // name in section names table 482 if (suffix) // suffix - back up over NUL and 483 { // append suffix string 484 section_names->setsize(section_names->size()-1); 539 if (suffix) 540 { // Append suffix string 541 section_names->setsize(section_names->size() - 1); // back up over terminating 0 485 542 section_names->writeString(suffix); 486 }; 543 } 544 IDXSTR *pidx = (IDXSTR *)section_names_hashtable->get(&namidx); 545 assert(!*pidx); // must not already exist 546 *pidx = namidx; 547 487 548 return elf_newsection2(namidx,type,flags,0,0,0,0,0,0,0); 488 549 } 489 550 490 551 /************************** 491 552 * Ouput read only data and generate a symbol for it. 492 553 * 493 554 */ 494 555 495 556 symbol *elf_sym_cdata(tym_t ty,char *p,int len) 496 557 { 497 558 symbol *s; 498 559 499 560 #if 0 500 561 if (OPT_IS_SET(OPTfwritable_strings)) 501 562 { 502 563 alignOffset(DATA, tysize(ty)); 503 564 s = symboldata(Doffset, ty); 504 565 SegData[DATA]->SDbuf->write(p,len); 505 566 s->Sseg = DATA; 506 567 s->Soffset = Doffset; // Remember its offset into DATA section … … 597 658 #define NAMIDX_STRTAB 9 // .strtab 598 659 #define NAMIDX_SHSTRTAB 17 // .shstrtab 599 660 #define NAMIDX_TEXT 27 // .text 600 661 #define NAMIDX_DATA 33 // .data 601 662 #define NAMIDX_BSS 39 // .bss 602 663 #define NAMIDX_NOTE 44 // .note 603 664 #define NAMIDX_COMMENT 50 // .comment 604 665 #define NAMIDX_RODATA 59 // .rodata 605 666 #define NAMIDX_RELTEXT 67 // .rel.text and .rela.text 606 667 #define NAMIDX_RELDATA 77 // .rel.data 607 668 #define NAMIDX_RELDATA64 78 // .rela.data 608 669 609 670 if (section_names) 610 671 section_names->setsize(sizeof(section_names_init64)); 611 672 else 612 673 { section_names = new Outbuffer(512); 613 674 section_names->reserve(1024); 614 675 section_names->writen(section_names_init64, sizeof(section_names_init64)); 615 676 } 616 677 678 if (section_names_hashtable) 679 delete section_names_hashtable; 680 section_names_hashtable = new AArray(&ti_idxstr, sizeof(IDXSTR)); 681 617 682 // name,type,flags,addr,offset,size,link,info,addralign,entsize 618 683 elf_newsection2(0, SHT_NULL, 0, 0,0,0,0,0, 0,0); 619 684 elf_newsection2(NAMIDX_TEXT,SHT_PROGDEF,SHF_ALLOC|SHF_EXECINSTR,0,0,0,0,0, 4,0); 620 685 elf_newsection2(NAMIDX_RELTEXT,SHT_RELA, 0,0,0,0,SHI_SYMTAB, SHI_TEXT, 8,8); 621 686 elf_newsection2(NAMIDX_DATA,SHT_PROGDEF,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 8,0); 622 687 elf_newsection2(NAMIDX_RELDATA64,SHT_RELA, 0,0,0,0,SHI_SYMTAB, SHI_DATA, 8,8); 623 688 elf_newsection2(NAMIDX_BSS, SHT_NOBITS,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 16,0); 624 689 elf_newsection2(NAMIDX_RODATA,SHT_PROGDEF,SHF_ALLOC, 0,0,0,0,0, 1,0); 625 690 elf_newsection2(NAMIDX_STRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 626 691 elf_newsection2(NAMIDX_SYMTAB,SHT_SYMTAB, 0, 0,0,0,0,0, 8,0); 627 692 elf_newsection2(NAMIDX_SHSTRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 628 693 elf_newsection2(NAMIDX_COMMENT, SHT_PROGDEF,0, 0,0,0,0,0, 1,0); 629 694 elf_newsection2(NAMIDX_NOTE,SHT_NOTE, 0, 0,0,0,0,0, 1,0); 695 696 IDXSTR namidx; 697 namidx = NAMIDX_TEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 698 namidx = NAMIDX_RELTEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 699 namidx = NAMIDX_DATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 700 namidx = NAMIDX_RELDATA64; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 701 namidx = NAMIDX_BSS; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 702 namidx = NAMIDX_RODATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 703 namidx = NAMIDX_STRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 704 namidx = NAMIDX_SYMTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 705 namidx = NAMIDX_SHSTRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 706 namidx = NAMIDX_COMMENT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 707 namidx = NAMIDX_NOTE; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 630 708 } 631 709 else 632 710 { 633 711 static char section_names_init[] = 634 712 "\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.bss\0.note\0.comment\0.rodata\0.rel.text\0.rel.data"; 635 713 636 714 if (section_names) 637 715 section_names->setsize(sizeof(section_names_init)); 638 716 else 639 717 { section_names = new Outbuffer(512); 640 section_names->reserve(10 24);718 section_names->reserve(100*1024); 641 719 section_names->writen(section_names_init, sizeof(section_names_init)); 642 720 } 721 722 if (section_names_hashtable) 723 delete section_names_hashtable; 724 section_names_hashtable = new AArray(&ti_idxstr, sizeof(IDXSTR)); 643 725 644 726 // name,type,flags,addr,offset,size,link,info,addralign,entsize 645 727 elf_newsection2(0, SHT_NULL, 0, 0,0,0,0,0, 0,0); 646 728 elf_newsection2(NAMIDX_TEXT,SHT_PROGDEF,SHF_ALLOC|SHF_EXECINSTR,0,0,0,0,0, 16,0); 647 729 elf_newsection2(NAMIDX_RELTEXT,SHT_REL, 0,0,0,0,SHI_SYMTAB, SHI_TEXT, 4,8); 648 730 elf_newsection2(NAMIDX_DATA,SHT_PROGDEF,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 4,0); 649 731 elf_newsection2(NAMIDX_RELDATA,SHT_REL, 0,0,0,0,SHI_SYMTAB, SHI_DATA, 4,8); 650 732 elf_newsection2(NAMIDX_BSS, SHT_NOBITS,SHF_ALLOC|SHF_WRITE, 0,0,0,0,0, 32,0); 651 733 elf_newsection2(NAMIDX_RODATA,SHT_PROGDEF,SHF_ALLOC, 0,0,0,0,0, 1,0); 652 734 elf_newsection2(NAMIDX_STRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 653 735 elf_newsection2(NAMIDX_SYMTAB,SHT_SYMTAB, 0, 0,0,0,0,0, 4,0); 654 736 elf_newsection2(NAMIDX_SHSTRTAB,SHT_STRTAB, 0, 0,0,0,0,0, 1,0); 655 737 elf_newsection2(NAMIDX_COMMENT, SHT_PROGDEF,0, 0,0,0,0,0, 1,0); 656 738 elf_newsection2(NAMIDX_NOTE,SHT_NOTE, 0, 0,0,0,0,0, 1,0); 739 740 IDXSTR namidx; 741 namidx = NAMIDX_TEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 742 namidx = NAMIDX_RELTEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 743 namidx = NAMIDX_DATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 744 namidx = NAMIDX_RELDATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 745 namidx = NAMIDX_BSS; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 746 namidx = NAMIDX_RODATA; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 747 namidx = NAMIDX_STRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 748 namidx = NAMIDX_SYMTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 749 namidx = NAMIDX_SHSTRTAB; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 750 namidx = NAMIDX_COMMENT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 751 namidx = NAMIDX_NOTE; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx; 657 752 } 658 753 659 754 if (SYMbuf) 660 755 SYMbuf->setsize(0); 661 756 symbol_idx = 0; 662 757 local_cnt = 0; 663 758 // The symbols that every object file has 664 759 elf_addsym(0, 0, 0, STT_NOTYPE, STB_LOCAL, 0); 665 760 elf_addsym(0, 0, 0, STT_FILE, STB_LOCAL, SHT_ABS); // STI_FILE 666 761 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_TEXT); // STI_TEXT 667 762 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_DATA); // STI_DATA 668 763 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_BSS); // STI_BSS 669 764 elf_addsym(0, 0, 0, STT_NOTYPE, STB_LOCAL, SHI_TEXT); // STI_GCC 670 765 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_RODAT); // STI_RODAT 671 766 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_NOTE); // STI_NOTE 672 767 elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHI_COM); // STI_COM 673 768 674 769 // Initialize output buffers for CODE, DATA and COMMENTS 675 770 // (NOTE not supported, BSS not required) 676 771 … … 1539 1634 pseg->SDbuf->reserve(1024); 1540 1635 } 1541 1636 } 1542 1637 if (pseg->SDrel) 1543 1638 pseg->SDrel->setsize(0); 1544 1639 pseg->SDsymidx = symidx; 1545 1640 pseg->SDrelidx = relidx; 1546 1641 pseg->SDrelmaxoff = 0; 1547 1642 pseg->SDrelindex = 0; 1548 1643 pseg->SDrelcnt = 0; 1549 1644 pseg->SDshtidxout = 0; 1550 1645 pseg->SDsym = NULL; 1551 1646 return seg; 1552 1647 } 1553 1648 1554 1649 int elf_getsegment(const char *name, const char *suffix, int type, int flags, 1555 1650 int align) 1556 1651 { 1557 1652 //printf("elf_getsegment(%s,%s,flags %x, align %d)\n",name,suffix,flags,align); 1558 1653 1559 IDXSTR namidx; 1560 if (namidx = elf_findstr(section_names,name,suffix)) 1561 { // this section name exists 1654 // Add name~suffix to the section_names table 1655 IDXSTR namidx = section_names->size(); 1656 section_names->writeString(name); 1657 if (suffix) 1658 { // Append suffix string 1659 section_names->setsize(section_names->size() - 1); // back up over terminating 0 1660 section_names->writeString(suffix); 1661 } 1662 IDXSTR *pidx = (IDXSTR *)section_names_hashtable->get(&namidx); 1663 if (*pidx) 1664 { // this section name already exists 1665 section_names->setsize(namidx); // remove addition 1666 namidx = *pidx; 1562 1667 for (int seg = CODE; seg <= seg_count; seg++) 1563 1668 { // should be in segment table 1564 1669 if (MAP_SEG2SEC(seg)->sh_name == namidx) 1565 1670 { 1566 1671 return seg; // found section for segment 1567 1672 } 1568 1673 } 1569 1674 assert(0); // but it's not a segment 1570 1675 // FIX - should be an error message conflict with section names 1571 1676 } 1677 *pidx = namidx; 1572 1678 1573 1679 //dbg_printf("\tNew segment - %d size %d\n", seg,SegData[seg]->SDbuf); 1574 IDXSEC shtidx = elf_newsection (name,suffix,type,flags);1680 IDXSEC shtidx = elf_newsection2(namidx,type,flags,0,0,0,0,0,0,0); 1575 1681 SecHdrTab[shtidx].sh_addralign = align; 1576 1682 IDXSYM symidx = elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, shtidx); 1577 1683 int seg = elf_getsegment2(shtidx, symidx, 0); 1578 1684 //printf("-elf_getsegment() = %d\n", seg); 1579 1685 return seg; 1580 1686 } 1581 1687 1582 1688 /******************************** 1583 1689 * Define a new code segment. 1584 1690 * Input: 1585 1691 * name name of segment, if NULL then revert to default 1586 1692 * suffix 0 use name as is 1587 1693 * 1 append "_TEXT" to name 1588 1694 * Output: 1589 1695 * cseg segment index of new current code segment 1590 1696 * Coffset starting offset in cseg 1591 1697 * Returns: 1592 1698 * segment index of newly created code segment 1593 1699 */ 1594 1700
