00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifdef USE_PCH
00036 #include "common_com_pch.h"
00037 #endif
00038 #pragma hdrstop
00039 #include <unistd.h>
00040 #include <sys/stat.h>
00041 #include <sys/mman.h>
00042 #include <fcntl.h>
00043 #include <elf.h>
00044 #include <sys/elf_whirl.h>
00045 #include <errno.h>
00046
00047 #ifndef USE_STANDARD_TYPES
00048 # define USE_STANDARD_TYPES
00049 #endif
00050
00051 #include "defs.h"
00052 #include "alignof.h"
00053 #ifdef OWN_ERROR_PACKAGE
00054
00055
00056
00057
00058 #define Is_True(x,y) (0)
00059 #define ERRORS_INCLUDED
00060 #else
00061 #include "erglob.h"
00062 #endif
00063 #include "errors.h"
00064 #include "opcode.h"
00065 #include "mempool.h"
00066 #include "strtab.h"
00067 #include "symtab.h"
00068 #include "const.h"
00069 #include "targ_const.h"
00070 #include "config_targ.h"
00071 #include "config_debug.h"
00072 #include "config_elf_targ.h"
00073 #include "irbdata.h"
00074 #include "wn_core.h"
00075 #include "wn.h"
00076 #include "wn_map.h"
00077 #define USE_DST_INTERNALS
00078 #include "dwarf_DST_mem.h"
00079 #include "pu_info.h"
00080 #include "ir_elf.h"
00081 #include "ir_bwrite.h"
00082 #include "ir_bcom.h"
00083 #include "ir_bread.h"
00084
00085 #if defined(BACK_END)
00086 #include "xstats.h"
00087 #endif
00088 #if defined(BACK_END) || defined(BUILD_WNPREFETCH)
00089 #include "pf_cg.h"
00090 #endif
00091
00092
00093
00094 static BOOL verbose_info = FALSE;
00095 static WN *last_node = NULL;
00096
00097 static off_t global_mapped_size;
00098 static off_t local_mapped_size;
00099
00100 static char file_revision[80];
00101
00102
00103 #define DOUBLE_ALIGNED(sz) (((sz) % 8) == 0 ? (sz) : (sz)+(8-((sz)%8)))
00104 #define ERROR_VALUE -1
00105
00106
00107
00108 #if defined(Is_True_On) || defined(DEBUG_IR)
00109
00110
00111 INT
00112 Error_Return_Func (void)
00113 {
00114 if (verbose_info && last_node != NULL) {
00115 printf("last_node at %p, opcode = %s\n",
00116 last_node, OPCODE_name(WN_opcode(last_node)));
00117 }
00118 return ERROR_VALUE;
00119 }
00120
00121 #define ERROR_RETURN Error_Return_Func()
00122 #else
00123 #define ERROR_RETURN ERROR_VALUE
00124 #endif
00125
00126
00127 template <class Shdr>
00128 const Shdr*
00129 get_section_header (const Shdr* shdr, UINT n, Elf64_Word type, Elf64_Word info)
00130 {
00131 for (INT i = 1; i < n; ++i) {
00132 if (shdr[i].sh_type == type && shdr[i].sh_info == info)
00133 return shdr + i;
00134 }
00135
00136 return NULL;
00137 }
00138
00139 OFFSET_AND_SIZE
00140 get_section (void *handle, Elf64_Word type, Elf64_Word info)
00141 {
00142 if (handle == 0 || handle == (void *)(ERROR_VALUE)) {
00143 errno = EINVAL;
00144 return OFFSET_AND_SIZE (0, 0);
00145 }
00146
00147 errno = 0;
00148
00149 Elf64_Ehdr *eh = (Elf64_Ehdr *) handle;
00150
00151 #ifndef __ALWAYS_USE_64BIT_ELF__
00152 if (eh->e_ident[EI_CLASS] == ELFCLASS32) {
00153 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) handle;
00154 const Elf32_Shdr* shdr = (const Elf32_Shdr *)
00155 ((char *) handle + ehdr->e_shoff);
00156 shdr = get_section_header (shdr, ehdr->e_shnum, type, info);
00157 if (!shdr)
00158 return OFFSET_AND_SIZE (0, 0);
00159 return OFFSET_AND_SIZE (shdr->sh_offset, shdr->sh_size);
00160 } else
00161 #endif
00162 {
00163 const Elf64_Shdr* shdr = (const Elf64_Shdr *)
00164 ((char *) handle + eh->e_shoff);
00165 shdr = get_section_header (shdr, eh->e_shnum, type, info);
00166 if (!shdr)
00167 return OFFSET_AND_SIZE (0, 0);
00168 return OFFSET_AND_SIZE (shdr->sh_offset, shdr->sh_size);
00169 }
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179 #if defined(Is_True_On) || defined(DEBUG_IR)
00180 #define CHECK_INPUT_FILES
00181 #endif
00182
00183 #ifdef CHECK_INPUT_FILES
00184
00185 #define CONVERT_OFFSET(typ, fld) \
00186 if ((INTPTR)(fld) >= size) return ERROR_RETURN; \
00187 else (fld) = (typ)(base + (INTPTR)(fld))
00188
00189 #else
00190
00191 #define CONVERT_OFFSET(typ, fld) \
00192 (fld) = (typ)(base + (INTPTR)(fld))
00193
00194 #endif // CHECK_INPUT_FILES
00195
00196
00197
00198
00199
00200
00201 INT
00202 WN_get_global_symtab (void *handle)
00203 {
00204
00205 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_GLOBALS);
00206 if (shdr.offset == 0)
00207 return ERROR_RETURN;
00208
00209 const char *base = (char *) handle + shdr.offset;
00210
00211 const GLOBAL_SYMTAB_HEADER_TABLE *gsymtab =
00212 (GLOBAL_SYMTAB_HEADER_TABLE *) base;
00213
00214 UINT64 size = shdr.size;
00215
00216 if (gsymtab->size < sizeof(gsymtab) ||
00217 gsymtab->entries < GLOBAL_SYMTAB_TABLES || gsymtab->size > size)
00218 return ERROR_RETURN;
00219
00220 UINT i;
00221 for (i = 0; i < GLOBAL_SYMTAB_TABLES; ++i)
00222 if (gsymtab->header[i].offset + gsymtab->header[i].size > size)
00223 return ERROR_RETURN;
00224
00225 for (i = 0; i < GLOBAL_SYMTAB_TABLES; ++i) {
00226 const SYMTAB_HEADER& hdr = gsymtab->header[i];
00227 const char *addr = base + hdr.offset;
00228
00229 switch (hdr.type) {
00230
00231 case SHDR_FILE:
00232 File_info = *((FILE_INFO *) addr);
00233 break;
00234
00235 case SHDR_ST:
00236 Scope_tab[GLOBAL_SYMTAB].st_tab->
00237 Transfer ((ST *) addr, hdr.size / hdr.entsize);
00238 break;
00239
00240 case SHDR_TY:
00241 Ty_tab.Transfer ((TY *) addr, hdr.size / hdr.entsize);
00242 break;
00243
00244 case SHDR_PU:
00245 Pu_Table.Transfer ((PU *) addr, hdr.size / hdr.entsize);
00246 break;
00247
00248 case SHDR_FLD:
00249 Fld_Table.Transfer ((FLD *) addr, hdr.size / hdr.entsize);
00250 break;
00251
00252 case SHDR_ARB:
00253 Arb_Table.Transfer ((ARB *) addr, hdr.size / hdr.entsize);
00254 break;
00255
00256 case SHDR_TYLIST:
00257 Tylist_Table.Transfer ((TYLIST *) addr, hdr.size / hdr.entsize);
00258 break;
00259
00260 case SHDR_TCON:
00261 Tcon_Table.Transfer ((TCON *) addr, hdr.size / hdr.entsize);
00262 break;
00263
00264 case SHDR_STR:
00265 Initialize_TCON_strtab (addr, hdr.size);
00266 break;
00267
00268 case SHDR_INITO:
00269 Scope_tab[GLOBAL_SYMTAB].inito_tab->
00270 Transfer ((INITO *) addr, hdr.size / hdr.entsize);
00271 break;
00272
00273 case SHDR_INITV:
00274 Initv_Table.Transfer ((INITV *) addr, hdr.size / hdr.entsize);
00275 break;
00276
00277 case SHDR_BLK:
00278 Blk_Table.Transfer ((BLK *) addr, hdr.size / hdr.entsize);
00279 break;
00280
00281 case SHDR_ST_ATTR:
00282 Scope_tab[GLOBAL_SYMTAB].st_attr_tab->
00283 Transfer ((ST_ATTR *) addr, hdr.size / hdr.entsize);
00284 break;
00285 }
00286 }
00287
00288 return 0;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298 INT
00299 WN_get_symtab (void *handle, PU_Info *pu)
00300 {
00301 Subsect_State st = PU_Info_state(pu, WT_SYMTAB);
00302 if (st == Subsect_InMem)
00303 return 0;
00304 else if (st != Subsect_Exists)
00305 return ERROR_RETURN;
00306
00307 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION);
00308 if (shdr.offset == 0)
00309 return ERROR_RETURN;
00310
00311 const char *base = (char *) handle + shdr.offset +
00312 PU_Info_subsect_offset (pu, WT_SYMTAB);
00313 Elf64_Word size = PU_Info_subsect_size(pu, WT_SYMTAB);
00314 const LOCAL_SYMTAB_HEADER_TABLE *lsymtab =
00315 (LOCAL_SYMTAB_HEADER_TABLE *) base;
00316
00317 if (lsymtab->size < sizeof(lsymtab) ||
00318 lsymtab->entries < LOCAL_SYMTAB_TABLES || lsymtab->size > size) {
00319 errno = EINVAL;
00320 return ERROR_RETURN;
00321 }
00322
00323 UINT i;
00324 for (i = 0; i < LOCAL_SYMTAB_TABLES; ++i)
00325 if (lsymtab->header[i].offset + lsymtab->header[i].size > size) {
00326 errno = EINVAL;
00327 return ERROR_RETURN;
00328 }
00329
00330 for (i = 0; i < LOCAL_SYMTAB_TABLES; ++i) {
00331 const SYMTAB_HEADER& hdr = lsymtab->header[i];
00332 const char *addr = base + hdr.offset;
00333
00334 switch (hdr.type) {
00335
00336 case SHDR_ST:
00337 Is_True(Scope_tab[CURRENT_SYMTAB].st_tab != 0,
00338 ("Null st_tab, level = %d", CURRENT_SYMTAB));
00339 Scope_tab[CURRENT_SYMTAB].st_tab->
00340 Transfer ((ST *) addr, hdr.size / hdr.entsize);
00341 break;
00342
00343 case SHDR_LABEL:
00344 Is_True(Scope_tab[CURRENT_SYMTAB].label_tab != 0,
00345 ("Null label_tab, level = %d", CURRENT_SYMTAB));
00346 Scope_tab[CURRENT_SYMTAB].label_tab->
00347 Transfer ((LABEL *) addr, hdr.size / hdr.entsize);
00348 break;
00349
00350 case SHDR_PREG:
00351 Is_True(Scope_tab[CURRENT_SYMTAB].preg_tab != 0,
00352 ("Null preg_tab, level = %d", CURRENT_SYMTAB));
00353 Scope_tab[CURRENT_SYMTAB].preg_tab->
00354 Transfer ((PREG *) addr, hdr.size / hdr.entsize);
00355 break;
00356
00357 case SHDR_INITO:
00358 Is_True(Scope_tab[CURRENT_SYMTAB].inito_tab != 0,
00359 ("Null inito_tab, level = %d", CURRENT_SYMTAB));
00360 Scope_tab[CURRENT_SYMTAB].inito_tab->
00361 Transfer ((INITO *) addr, hdr.size / hdr.entsize);
00362 break;
00363
00364 case SHDR_ST_ATTR:
00365 Is_True(Scope_tab[CURRENT_SYMTAB].st_attr_tab != 0,
00366 ("Null st_attr_tab, level = %d", CURRENT_SYMTAB));
00367 Scope_tab[CURRENT_SYMTAB].st_attr_tab->
00368 Transfer ((ST_ATTR *) addr, hdr.size / hdr.entsize);
00369 break;
00370 }
00371 }
00372
00373 Set_PU_Info_state(pu, WT_SYMTAB, Subsect_InMem);
00374
00375 return 0;
00376 }
00377
00378
00379 INT
00380 WN_get_strtab (void *handle)
00381 {
00382 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_STRTAB);
00383 if (shdr.offset == 0)
00384 return ERROR_RETURN;
00385
00386 Initialize_Strtab ((char *) handle + shdr.offset, shdr.size);
00387
00388 return 0;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 static INT
00398 fix_tree (WN *node, char *base, Elf64_Word size)
00399 {
00400 OPCODE opcode = (OPCODE) WN_opcode (node);
00401 WN *wn;
00402
00403 #if defined(Is_True_On) || defined(DEBUG_IR)
00404 if (verbose_info) {
00405 printf("opcode %s\n", OPCODE_name(opcode));
00406 last_node = node;
00407 }
00408 #endif
00409
00410 #ifndef CFE
00411 if (opcode == OPC_REGION)
00412 Set_Max_Region_Id (WN_region_id(node));
00413 #endif
00414
00415 #if defined(BACK_END)
00416 if (opcode == OPC_ALTENTRY)
00417 Set_PU_has_altentry (Get_Current_PU ());
00418
00419
00420 Count_WN_Opcode (opcode, &PU_WN_BB_Cnt, &PU_WN_Stmt_Cnt);
00421 #endif
00422
00423 if (opcode == OPC_BLOCK) {
00424 wn = WN_first(node);
00425 if (wn == (WN *) -1) {
00426 WN_first(node) = NULL;
00427 WN_last(node) = NULL;
00428 } else {
00429 CONVERT_OFFSET(WN*, wn);
00430 WN_first(node) = wn;
00431 CONVERT_OFFSET(WN*, WN_last(node));
00432
00433 do {
00434 if (fix_tree (wn, base, size) == ERROR_VALUE)
00435 return ERROR_VALUE;
00436 wn = WN_next(wn);
00437 } while (wn);
00438 }
00439 } else if (!OPCODE_is_leaf(opcode)) {
00440 register INT i, cnt;
00441 register WN **wn_ptr;
00442
00443 cnt = WN_kid_count(node);
00444 wn_ptr = &WN_kid(node, 0);
00445 for (i = 0; i < cnt; i++, wn_ptr++) {
00446 wn = *wn_ptr;
00447 if (wn == (WN *) -1) {
00448 *wn_ptr = NULL;
00449 } else {
00450 CONVERT_OFFSET(WN*, wn);
00451 *wn_ptr = wn;
00452 if (fix_tree (wn, base, size) == ERROR_VALUE)
00453 return ERROR_VALUE;
00454 }
00455 }
00456 }
00457
00458 if (OPCODE_has_next_prev(opcode)) {
00459 wn = WN_prev(node);
00460 if (wn == (WN *) -1) {
00461 WN_prev(node) = NULL;
00462 } else {
00463 CONVERT_OFFSET(WN*, wn);
00464 WN_prev(node) = wn;
00465 }
00466 wn = WN_next(node);
00467 if (wn == (WN *) -1) {
00468 WN_next(node) = NULL;
00469 } else {
00470 CONVERT_OFFSET(WN*, wn);
00471 WN_next(node) = wn;
00472 }
00473 }
00474
00475
00476 if (WN_map_id(node) != -1) {
00477 register OPERATOR_MAPCAT category = OPCODE_mapcat(opcode);
00478 register INT32 map_id = WN_map_id(node);
00479 register INT32 *last_id_ptr;
00480
00481 last_id_ptr = &WN_MAP_TAB_Last_ID(Current_Map_Tab, category);
00482 if (map_id > *last_id_ptr) {
00483 *last_id_ptr = map_id;
00484 }
00485 }
00486
00487 return 0;
00488 }
00489
00490
00491
00492 void
00493 Set_Verbose_Info (BOOL val)
00494 {
00495 verbose_info = val;
00496 }
00497
00498
00499 template <class ELF>
00500 INT
00501 check_elf_header (const char* baseaddr, Elf64_Word size, const ELF& tag)
00502 {
00503 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr*) baseaddr;
00504 if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
00505 ehdr->e_version != EV_CURRENT) {
00506 return ERROR_RETURN;
00507 }
00508 if (ehdr->e_type != ET_IR
00509 || ehdr->e_shentsize != sizeof(typename ELF::Elf_Shdr)) {
00510 return ERROR_RETURN;
00511 }
00512 if (Target_ABI != ABI_UNDEF &&
00513
00514 ehdr->e_machine != Get_Elf_Target_Machine())
00515 return ABI_MISMATCH;
00516 BOOL is_64bit;
00517 INT isa;
00518 Config_Target_From_ELF (ehdr->e_flags, &is_64bit, &isa);
00519 if ( ! Set_Target_ABI (is_64bit, isa))
00520 return ABI_MISMATCH;
00521 if (ehdr->e_shstrndx >= ehdr->e_shnum) {
00522 return ERROR_RETURN;
00523 }
00524 if (ehdr->e_shoff >= size ||
00525 ehdr->e_shoff + ehdr->e_shnum * sizeof(typename ELF::Elf_Shdr) > size) {
00526 return ERROR_RETURN;
00527 }
00528 typename ELF::Elf_Shdr* shdr =
00529 (typename ELF::Elf_Shdr *) (baseaddr + ehdr->e_shoff);
00530 if ((long) shdr & (ALIGNOF(typename ELF::Elf_Shdr) - 1)) {
00531 return ERROR_RETURN;
00532 }
00533 return tag.Elf_class();
00534 }
00535
00536
00537 static INT
00538 check_elf_header (const char *baseaddr, Elf64_Word size)
00539 {
00540 if (size < sizeof(Elf64_Ehdr))
00541 return ERROR_RETURN;
00542 Elf64_Ehdr* ehdr = (Elf64_Ehdr *) baseaddr;
00543 if (!IS_ELF (*ehdr))
00544 return ERROR_RETURN;
00545 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) {
00546 return check_elf_header (baseaddr, size, ELF64()); }
00547
00548 #ifndef __ALWAYS_USE_64BIT_ELF__
00549 else if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
00550 return check_elf_header (baseaddr, size, ELF32());
00551 #endif
00552 else
00553 return ERROR_RETURN;
00554 }
00555
00556
00557
00558 template <class ELF>
00559 INT
00560 check_section_headers (char *baseaddr, Elf64_Word size,
00561 char* file_revision, const ELF& tag)
00562 {
00563 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr*) baseaddr;
00564 typename ELF::Elf_Shdr* shdr =
00565 (typename ELF::Elf_Shdr*) (baseaddr + ehdr->e_shoff);
00566
00567 errno = ENOEXEC;
00568
00569 if (shdr[ehdr->e_shstrndx].sh_offset >= size ||
00570 shdr[ehdr->e_shstrndx].sh_offset +
00571 shdr[ehdr->e_shstrndx].sh_size > size)
00572 return ERROR_RETURN;
00573
00574 char* shstrtab = baseaddr + shdr[ehdr->e_shstrndx].sh_offset;
00575
00576 for (INT i = 1; i < ehdr->e_shnum; i++) {
00577 if (shdr[i].sh_offset >= size ||
00578 shdr[i].sh_offset + shdr[i].sh_size > size)
00579 return ERROR_RETURN;
00580 if (shdr[i].sh_name >= shdr[ehdr->e_shstrndx].sh_size)
00581 return ERROR_RETURN;
00582 if (shdr[i].sh_link >= ehdr->e_shnum)
00583 return ERROR_RETURN;
00584 if (shdr[i].sh_addralign & (shdr[i].sh_addralign - 1))
00585 return ERROR_RETURN;
00586 if (shdr[i].sh_addralign > 1 &&
00587 (long)(baseaddr + shdr[i].sh_offset) & ((shdr[i].sh_addralign - 1)))
00588 return ERROR_RETURN;
00589
00590
00591 if (shdr[i].sh_type == SHT_PROGBITS &&
00592 strcmp (shstrtab + shdr[i].sh_name, ELF_COMMENT) == 0) {
00593 register char *p = baseaddr + shdr[i].sh_offset;
00594 register char *eob = p + shdr[i].sh_size - 1;
00595 register int match = 0;
00596
00597 if (*eob != 0)
00598
00599 return ERROR_RETURN;
00600
00601 while (p <= eob) {
00602 if (strncmp ("WHIRL:", p, 6) == 0) {
00603 strcpy (file_revision, p);
00604 if (strcmp (WHIRL_REVISION, p) == 0) {
00605 match = 1;
00606 break;
00607 }
00608 }
00609 p += strlen (p) + 1;
00610 }
00611
00612 if (!match && DEBUG_Ir_Version_Check)
00613 return REVISION_MISMATCH;
00614 }
00615 }
00616
00617 errno = 0;
00618 return 1;
00619 }
00620
00621 static INT
00622 fix_comp_flags (char *base, Elf64_Word size)
00623 {
00624 register char **argv;
00625 register Elf64_Word argc;
00626
00627 if (sizeof(Elf64_Word) > size)
00628 return ERROR_RETURN;
00629
00630 argc = *((Elf64_Word *) base);
00631
00632 if (sizeof(Elf64_Word) + argc * sizeof(Elf64_Word) > size)
00633 return ERROR_RETURN;
00634 argv = (char **) (base + sizeof(Elf64_Word));
00635
00636 while (argc--) {
00637 register Elf64_Word offset = *((Elf64_Word *)argv);
00638
00639 if (offset > size)
00640 return ERROR_RETURN;
00641 *argv = base + offset;
00642 argv++;
00643 }
00644
00645 return 0;
00646 }
00647
00648
00649
00650 INT
00651 WN_massage_input (char *baseaddr, Elf64_Word size, char* file_revision)
00652 {
00653 INT st;
00654
00655 if ((st = check_elf_header (baseaddr, size)) < 0)
00656 return st;
00657
00658 #ifndef __ALWAYS_USE_64BIT_ELF__
00659 if (st == ELFCLASS32) {
00660 if ((st = check_section_headers (baseaddr, size, file_revision,
00661 ELF32())) <= 0)
00662 return st;
00663 } else
00664 #endif
00665 {
00666 if ((st = check_section_headers (baseaddr, size, file_revision,
00667 ELF64())) <= 0)
00668 return st;
00669 }
00670
00671 return 1;
00672 }
00673
00674
00675
00676 static void *
00677 read_file (const char *filename, off_t* mapped_size, char* file_revision)
00678 {
00679 int fd;
00680 INT st;
00681 struct stat stat_buf;
00682 register char *map_addr;
00683
00684 fd = open (filename, O_RDONLY);
00685 if (fd < 0)
00686 return (void *) ERROR_RETURN;
00687
00688 if (fstat (fd, &stat_buf) != 0)
00689 return (void *) ERROR_RETURN;
00690
00691 map_addr = (char *) mmap (0, stat_buf.st_size, PROT_READ|PROT_WRITE,
00692 MAP_PRIVATE, fd, 0);
00693 if (map_addr == (char *)(ERROR_VALUE)) {
00694 close (fd);
00695 return (void *) ERROR_RETURN;
00696 }
00697
00698 close (fd);
00699
00700 if ((st = WN_massage_input(map_addr, stat_buf.st_size,
00701 file_revision)) <= 0) {
00702 munmap (map_addr, stat_buf.st_size);
00703 return (void *) (st);
00704 }
00705
00706
00707 *mapped_size = stat_buf.st_size;
00708 return map_addr;
00709
00710 }
00711
00712
00713 Elf64_Word
00714 Get_Elf_Section_Size (void *handle, Elf64_Word type, Elf64_Word info)
00715 {
00716 OFFSET_AND_SIZE shdr = get_section (handle, type, info);
00717 if (shdr.offset == 0) return 0;
00718 return shdr.size;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728 void *
00729 WN_open_input (const char *filename, off_t *mapped_size)
00730 {
00731 if (filename == 0) {
00732 errno = ENOENT;
00733 return (void *) ERROR_RETURN;
00734 }
00735
00736 errno = 0;
00737
00738 return read_file (filename, mapped_size, file_revision);
00739
00740 }
00741
00742
00743
00744
00745
00746
00747 extern void *
00748 WN_inline_open_file(const char* file_name, off_t *mapped_size,
00749 char* file_revision)
00750 {
00751 if (file_name == 0) {
00752 errno = ENOENT;
00753 return (void *) ERROR_RETURN;
00754 }
00755
00756 errno = 0;
00757
00758 return read_file (file_name, mapped_size, file_revision);
00759
00760 }
00761
00762
00763
00764
00765
00766
00767
00768
00769 PU_Info *
00770 WN_get_PU_Infos (void *handle, INT32 *p_num_PUs)
00771 {
00772 char *base;
00773 INT32 size;
00774 PU_Info *pu_tree;
00775
00776 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION);
00777 if (shdr.offset == 0) return (PU_Info *)ERROR_RETURN;
00778
00779 base = (char *) handle + shdr.offset;
00780 size = shdr.size;
00781
00782 pu_tree = Read_PU_Infos (base, size, p_num_PUs);
00783 if (pu_tree == (PU_Info *)ERROR_VALUE)
00784 return (PU_Info *)ERROR_RETURN;
00785
00786 return pu_tree;
00787 }
00788
00789
00790 #ifdef BACK_END
00791 void *
00792 WN_get_section_base (void *handle, INT sect)
00793 {
00794 char *base;
00795
00796 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, sect);
00797 if (shdr.offset == 0) return (void *) ERROR_RETURN;
00798
00799 base = (char *) handle + shdr.offset;
00800 return (void *) base;
00801 }
00802 #endif
00803
00804
00805
00806
00807
00808
00809
00810 ST *
00811 WN_get_proc_sym (PU_Info *pu)
00812 {
00813 Subsect_State st = PU_Info_state(pu, WT_PROC_SYM);
00814
00815 if (st == Subsect_InMem)
00816 return &St_Table[PU_Info_proc_sym(pu)];
00817 if (st != Subsect_Exists)
00818 return (ST *) ERROR_RETURN;
00819 ST *ps = &St_Table[PU_Info_proc_sym(pu)];
00820 if (ps == NULL)
00821 return (ST *) ERROR_RETURN;
00822
00823 Set_PU_Info_state(pu, WT_PROC_SYM, Subsect_InMem);
00824
00825 return ps;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835 WN *
00836 WN_get_tree (void *handle, PU_Info *pu)
00837 {
00838 register char *section_base, *tree_base;
00839 register Elf64_Word offset, size;
00840 WN *wn;
00841 Elf64_Word first_node;
00842 Subsect_State st = PU_Info_state(pu, WT_TREE);
00843
00844 if (st == Subsect_InMem)
00845 return PU_Info_tree_ptr(pu);
00846 if (st != Subsect_Exists)
00847 return (WN *) ERROR_RETURN;
00848
00849 offset = PU_Info_subsect_offset(pu, WT_TREE);
00850 size = PU_Info_subsect_size(pu, WT_TREE);
00851
00852 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION);
00853 if (shdr.offset == 0) return (WN *) ERROR_RETURN;
00854
00855 if (offset + size > shdr.size) {
00856 errno = EINVAL;
00857 return (WN *) ERROR_RETURN;
00858 }
00859
00860 section_base = (char *) handle + shdr.offset;
00861 tree_base = section_base + offset;
00862
00863
00864 first_node = *(Elf64_Word *)tree_base;
00865 wn = (WN *) (tree_base + first_node);
00866
00867 #ifndef CFE
00868 Set_Max_Region_Id(0);
00869 #endif
00870
00871
00872
00873
00874
00875 Current_Map_Tab = PU_Info_maptab(pu);
00876 if (fix_tree (wn, tree_base, size) == ERROR_VALUE)
00877 return (WN *)ERROR_VALUE;
00878
00879 WN_next(wn) = NULL;
00880 WN_prev(wn) = NULL;
00881
00882 Set_PU_Info_tree_ptr(pu, wn);
00883 Set_PU_Info_state(pu, WT_TREE, Subsect_InMem);
00884
00885 return wn;
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 INT
00898 WN_get_flags (void *handle, char ***argv)
00899 {
00900 Elf64_Word argc;
00901 char *baseaddr;
00902
00903 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_COMP_FLAGS);
00904 if (shdr.offset == 0) return 0;
00905
00906 baseaddr = (char *) handle + shdr.offset;
00907 if (fix_comp_flags (baseaddr, shdr.size) == ERROR_VALUE)
00908 return 0;
00909 argc = *((Elf64_Word *) baseaddr);
00910 *argv = (char **) (baseaddr + sizeof(Elf64_Word));
00911
00912 return argc;
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922 INT
00923 WN_get_dst (void *handle)
00924 {
00925 register INT size, num_blocks;
00926 char *base, *ptr, *blk;
00927 DST_BLOCK_IDX j;
00928
00929 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_DST);
00930 if (shdr.offset == 0) return ERROR_RETURN;
00931
00932 base = (char *) handle + shdr.offset;
00933 size = shdr.size;
00934
00935
00936 ptr = base + size - sizeof(mINT32);
00937 num_blocks = *(INT32*) ptr;
00938 num_blocks++;
00939 ptr -= (num_blocks * sizeof(block_header));
00940
00941 DST_Init (ptr, num_blocks);
00942 FOREACH_DST_BLOCK(j) {
00943 blk = ((DST_Type *)Current_DST)->dst_blocks[j].offset;
00944 if (blk == (char *)-1) {
00945 ((DST_Type *)Current_DST)->dst_blocks[j].offset = NULL;
00946 } else {
00947 CONVERT_OFFSET(char*, blk);
00948 ((DST_Type *)Current_DST)->dst_blocks[j].offset = blk;
00949 }
00950 }
00951
00952 return size;
00953 }
00954
00955
00956 #if defined(BACK_END) || defined(IR_TOOLS)
00957
00958 INT
00959 WN_get_feedback (void* handle, PU_Info* pu, MEM_POOL* pool)
00960 {
00961 Subsect_State st = PU_Info_state(pu, WT_FEEDBACK);
00962
00963 switch (st) {
00964 case Subsect_Missing:
00965 case Subsect_InMem:
00966 default:
00967 return 0;
00968 case Subsect_Exists:
00969 break;
00970 case Subsect_Written:
00971 return ERROR_RETURN;
00972 }
00973
00974 Elf64_Word offset = PU_Info_subsect_offset (pu, WT_FEEDBACK);
00975 Elf64_Word size = PU_Info_subsect_size (pu, WT_FEEDBACK);
00976 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION);
00977 if (shdr.offset == 0)
00978 return ERROR_RETURN;
00979
00980 if (offset + size >= shdr.size) {
00981 errno = EINVAL;
00982 return ERROR_RETURN;
00983 }
00984
00985 INTPTR baseaddr = (INTPTR)handle + shdr.offset + offset;
00986
00987 Set_PU_Info_feedback_ptr (pu, baseaddr);
00988 Set_PU_Info_state (pu, WT_FEEDBACK, Subsect_InMem);
00989
00990 return 0;
00991 }
00992 #endif
00993
00994
00995
00996 #if defined(BACK_END) || defined(BUILD_WNPREFETCH)
00997
00998 INT
00999 WN_get_prefetch (void *handle, PU_Info *pu)
01000 {
01001 Elf64_Word offset, size;
01002 char *cur_addr, *end_addr, *tree_base;
01003 Elf64_Word node_offset;
01004 WN *node;
01005 PF_POINTER *pf_ptr;
01006 Subsect_State st = PU_Info_state(pu, WT_PREFETCH);
01007 Current_Map_Tab = PU_Info_maptab(pu);
01008
01009 if (st == Subsect_Written)
01010 return ERROR_RETURN;
01011 if (st != Subsect_Exists)
01012 return 0;
01013
01014 offset = PU_Info_subsect_offset(pu, WT_PREFETCH);
01015 size = PU_Info_subsect_size(pu, WT_PREFETCH);
01016
01017 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION);
01018 if (shdr.offset == 0) return ERROR_RETURN;
01019
01020 if (offset + size >= shdr.size) {
01021 errno = EINVAL;
01022 return ERROR_RETURN;
01023 }
01024
01025
01026 tree_base = (char *) handle + shdr.offset +
01027 PU_Info_subsect_offset(pu, WT_TREE);
01028
01029 cur_addr = (char *)handle + shdr.offset + offset;
01030 end_addr = cur_addr + size;
01031
01032 for (;;) {
01033 node_offset = *(Elf64_Word *)cur_addr;
01034 cur_addr += (sizeof(Elf64_Word));
01035
01036 if (node_offset == (Elf64_Word)-1) break;
01037
01038 cur_addr = (char *)ir_b_align((off_t)cur_addr, ALIGNOF(PF_POINTER),
01039 0);
01040 pf_ptr = (PF_POINTER *)cur_addr;
01041 cur_addr += (sizeof(PF_POINTER));
01042
01043
01044 node = (WN *)(tree_base + node_offset);
01045 if (pf_ptr->wn_pref_1L == (WN*) -1) {
01046 pf_ptr->wn_pref_1L = NULL;
01047 } else {
01048 pf_ptr->wn_pref_1L =
01049 (WN*)(tree_base + (INTPTR)pf_ptr->wn_pref_1L);
01050 }
01051
01052 if (pf_ptr->wn_pref_2L == (WN*) -1) {
01053 pf_ptr->wn_pref_2L = NULL;
01054 } else {
01055 pf_ptr->wn_pref_2L =
01056 (WN*)(tree_base + (INTPTR)pf_ptr->wn_pref_2L);
01057 }
01058
01059
01060 WN_MAP_Set(WN_MAP_PREFETCH, node, (void *)pf_ptr);
01061
01062 if (cur_addr > end_addr) return ERROR_RETURN;
01063 }
01064
01065 PU_Info_subsect_ptr(pu, WT_PREFETCH) = NULL;
01066 Set_PU_Info_state(pu, WT_PREFETCH, Subsect_InMem);
01067
01068 return 0;
01069 }
01070
01071 #endif
01072
01073 static inline void
01074 WN_MAP_put(WN_MAP wn_map, WN *wn, INT32 value)
01075 {
01076 WN_MAP32_Set(wn_map, wn, value);
01077 }
01078
01079 static inline void
01080 WN_MAP_put(WN_MAP wn_map, WN *wn, INT64 value)
01081 {
01082 WN_MAP64_Set(wn_map, wn, value);
01083 }
01084
01085 static inline void
01086 WN_MAP_put(WN_MAP wn_map, WN *wn, void *value)
01087 {
01088 WN_MAP_Set(wn_map, wn, value);
01089 }
01090
01091 template<class MAP_ENTRY_TYPE>
01092 static inline INT
01093 WN_read_generic_map(void *handle,
01094 PU_Info *pu,
01095 INT32 subsection_type,
01096 WN_MAP value_map,
01097 MAP_ENTRY_TYPE)
01098 {
01099 Subsect_State state = PU_Info_state (pu, subsection_type);
01100 Elf64_Word offset, size;
01101 char *cur_addr, *end_addr, *tree_base;
01102
01103 if (state == Subsect_Written) {
01104 return ERROR_RETURN;
01105 }
01106 if (state != Subsect_Exists) {
01107 return 0;
01108 }
01109
01110 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION);
01111 if (shdr.offset == 0) {
01112 return ERROR_RETURN;
01113 }
01114
01115 offset = PU_Info_subsect_offset(pu, subsection_type);
01116 size = PU_Info_subsect_size(pu, subsection_type);
01117
01118 if (offset + size >= shdr.size) {
01119 errno = EINVAL;
01120 return ERROR_RETURN;
01121 }
01122
01123
01124 tree_base = (char *) handle + shdr.offset +
01125 PU_Info_subsect_offset(pu, WT_TREE);
01126
01127 cur_addr = (char *)handle + shdr.offset + offset;
01128 end_addr = cur_addr + size;
01129
01130 for (;;) {
01131 MAP_ENTRY_TYPE map_value;
01132 Elf64_Word node_offset = *(Elf64_Word *) cur_addr;
01133 WN *node;
01134
01135 cur_addr += (sizeof(Elf64_Word));
01136
01137 if (node_offset == (Elf64_Word)-1)
01138 break;
01139
01140
01141 cur_addr = (char *) ir_b_align ((off_t) cur_addr,
01142 sizeof(MAP_ENTRY_TYPE),
01143 0);
01144 map_value = * (MAP_ENTRY_TYPE *) cur_addr;
01145 cur_addr += sizeof(MAP_ENTRY_TYPE);
01146
01147 node = (WN *) (tree_base + node_offset);
01148
01149
01150
01151 WN_MAP_put(value_map, node, map_value);
01152
01153 if (cur_addr > end_addr)
01154 return ERROR_RETURN;
01155 }
01156
01157 PU_Info_subsect_ptr(pu, subsection_type) = NULL;
01158 Set_PU_Info_state(pu, subsection_type, Subsect_InMem);
01159
01160 return 0;
01161 }
01162
01163 INT
01164 WN_get_INT32_map(void *handle,
01165 PU_Info *pu,
01166 INT32 subsection_type,
01167 WN_MAP value_map)
01168 {
01169 return WN_read_generic_map(handle, pu, subsection_type,
01170 value_map, (INT32) 0);
01171 }
01172
01173 INT
01174 WN_get_voidptr_map(void *handle,
01175 PU_Info *pu,
01176 INT32 subsection_type,
01177 WN_MAP value_map)
01178 {
01179 return WN_read_generic_map(handle, pu, subsection_type,
01180 value_map, (void *) 0);
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191 void
01192 WN_free_input (void *handle, off_t mapped_size)
01193 {
01194 if (handle == 0 || handle == (void *)(-1))
01195 return;
01196
01197
01198 munmap ((char*)handle, mapped_size);
01199 }
01200
01201
01202 #ifndef OWN_ERROR_PACKAGE
01203
01204
01205
01206
01207
01208 static void *global_fhandle;
01209 static void *local_fhandle;
01210 static const char *global_ir_file;
01211 static const char *local_ir_file;
01212
01213 static void
01214 open_specified_input (const char *input_file, const char **ir_input,
01215 void **fhandle, off_t *mapped_size)
01216 {
01217 Set_Error_Phase ( "Reading WHIRL file" );
01218 *ir_input = input_file;
01219 *fhandle = WN_open_input (input_file, mapped_size);
01220
01221 if (*fhandle == (void*) REVISION_MISMATCH) {
01222 ErrMsg ( EC_IR_Revision, file_revision, *ir_input);
01223 } else if (*fhandle == (void*) ABI_MISMATCH) {
01224 ErrMsg ( EC_IR_Revision,
01225 "abi of whirl file doesn't match abi from command-line",
01226 *ir_input);
01227 } else if (*fhandle == (void*) READER_ERROR) {
01228 ErrMsg ( EC_IR_Open, *ir_input, errno );
01229 }
01230 }
01231
01232
01233 void *
01234 Open_Input_Info (const char *input_file)
01235 {
01236 open_specified_input (input_file,
01237 &global_ir_file, &global_fhandle, &global_mapped_size);
01238 local_ir_file = global_ir_file;
01239 local_fhandle = global_fhandle;
01240 local_mapped_size = global_mapped_size;
01241 return global_fhandle;
01242 }
01243
01244 void *
01245 Open_Global_Input (const char *input_file)
01246 {
01247 open_specified_input (input_file,
01248 &global_ir_file, &global_fhandle, &global_mapped_size);
01249 return global_fhandle;
01250 }
01251
01252 void *
01253 Open_Local_Input (const char *input_file)
01254 {
01255 open_specified_input (input_file,
01256 &local_ir_file, &local_fhandle, &local_mapped_size);
01257 return local_fhandle;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266 PU_Info *
01267 Read_Global_Info (INT32 *p_num_PUs)
01268 {
01269 PU_Info *pu_tree;
01270
01271 Set_Error_Phase ( "Reading WHIRL file" );
01272
01273 if (WN_get_strtab(global_fhandle) == -1) {
01274 ErrMsg ( EC_IR_Scn_Read, "strtab", global_ir_file);
01275 }
01276
01277 if ((INT) WN_get_global_symtab (global_fhandle) == -1) {
01278 ErrMsg ( EC_IR_Scn_Read, "global symtab", global_ir_file);
01279 }
01280
01281
01282
01283 if (WN_get_dst(local_fhandle) == -1) {
01284 ErrMsg ( EC_IR_Scn_Read, "dst", local_ir_file);
01285 }
01286
01287
01288 pu_tree = WN_get_PU_Infos (local_fhandle, p_num_PUs);
01289 if (pu_tree == (PU_Info *)-1) {
01290 ErrMsg ( EC_IR_Scn_Read, "PU headers", local_ir_file);
01291 }
01292 if (verbose_info) {
01293 printf("done reading global info\n");
01294 }
01295
01296 return pu_tree;
01297 }
01298
01299
01300 void
01301 Read_Local_Info (MEM_POOL *pool, PU_Info *pu)
01302 {
01303 const char *save_phase = Get_Error_Phase();
01304 Set_Error_Phase ( "Reading WHIRL file" );
01305
01306
01307 Current_Map_Tab = PU_Info_maptab(pu);
01308 if (!Current_Map_Tab) {
01309 Current_Map_Tab = WN_MAP_TAB_Create(pool);
01310 PU_Info_maptab(pu) = Current_Map_Tab;
01311 }
01312
01313 CURRENT_SYMTAB = PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)]);
01314 New_Scope (CURRENT_SYMTAB, MEM_pu_nz_pool_ptr, FALSE);
01315
01316 if (WN_get_symtab (local_fhandle, pu) == -1)
01317 ErrMsg ( EC_IR_Scn_Read, "local symtab", local_ir_file);
01318
01319 Scope_tab[CURRENT_SYMTAB].st = WN_get_proc_sym (pu);
01320 if (Scope_tab[CURRENT_SYMTAB].st == (ST *) -1)
01321 ErrMsg ( EC_IR_Scn_Read, "proc ST", local_ir_file);
01322 else
01323 Current_pu = &Pu_Table[ST_pu (Scope_tab[CURRENT_SYMTAB].st)];
01324
01325
01326 if (WN_get_tree (local_fhandle, pu) == (WN*) -1) {
01327 ErrMsg ( EC_IR_Scn_Read, "tree", local_ir_file);
01328 }
01329
01330 #if defined(BACK_END) || defined(BUILD_WNPREFETCH)
01331 if (WN_get_prefetch (local_fhandle, pu) == -1) {
01332 ErrMsg ( EC_IR_Scn_Read, "prefetch map", local_ir_file);
01333 }
01334 #endif
01335
01336
01337 if (WN_get_INT32_map(local_fhandle, pu,
01338 WT_ALIAS_CLASS, WN_MAP_ALIAS_CLASS) == -1) {
01339 ErrMsg ( EC_IR_Scn_Read, "alias class map", local_ir_file);
01340 }
01341
01342 if (WN_get_voidptr_map(local_fhandle, pu,
01343 WT_AC_INTERNAL, WN_MAP_AC_INTERNAL) == -1) {
01344 ErrMsg ( EC_IR_Scn_Read, "alias class internal map", local_ir_file);
01345 }
01346
01347 Set_Error_Phase(save_phase);
01348 }
01349
01350
01351 void
01352 Free_Local_Info (PU_Info *pu)
01353 {
01354 Delete_Scope (PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)]));
01355
01356
01357 if (PU_Info_maptab(pu)) {
01358 WN_MAP_TAB_Delete(PU_Info_maptab(pu));
01359 PU_Info_maptab(pu) = NULL;
01360 }
01361 }
01362
01363 void
01364 Free_Local_Input(void)
01365 {
01366 WN_free_input(local_fhandle, local_mapped_size);
01367 local_fhandle = 0;
01368 }
01369
01370 void
01371 Free_Input_Info (void)
01372 {
01373 WN_free_input(global_fhandle, global_mapped_size);
01374 if (global_fhandle != local_fhandle) {
01375 Free_Local_Input();
01376 }
01377 global_fhandle = 0;
01378 }
01379
01380 #endif
01381