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
00036
00037
00038
00039
00040 #define __STDC_LIMIT_MACROS
00041 #include <stdint.h>
00042 #if defined(BUILD_OS_DARWIN)
00043 #include <darwin_elf.h>
00044 #else
00045 #include <elf.h>
00046 #endif
00047 #include <sys/elf_whirl.h>
00048
00049 #include "linker.h"
00050 #include "read.h"
00051 #include "ipc_weak.h"
00052
00053 #include "defs.h"
00054 #include "cxx_memory.h"
00055 #include "erglob.h"
00056 #include "symtab.h"
00057
00058 #include "ld_ipa_interface.h"
00059 #include "ipc_link.h"
00060 #include "dwarf_DST_mem.h"
00061 #include "ipc_file.h"
00062 #include "ipc_symtab_merge.h"
00063 #include "ipc_main.h"
00064 #include "ir_bread.h"
00065
00066 static void
00067 get_global_symtab (IPC_GLOBAL_TABS >abs, FILE_INFO &finfo,
00068 an_object_file_ptr p_obj,
00069 const GLOBAL_SYMTAB_HEADER_TABLE *gsymtab)
00070 {
00071
00072
00073
00074
00075 gtabs.p_obj = p_obj;
00076
00077 for (UINT i = 0; i < GLOBAL_SYMTAB_TABLES; ++i) {
00078 const SYMTAB_HEADER &hdr = gsymtab->header[i];
00079 char *addr = (char *)gsymtab + hdr.offset;
00080
00081 switch (hdr.type) {
00082
00083 case SHDR_FILE:
00084 finfo = *((FILE_INFO *) addr);
00085 break;
00086
00087 case SHDR_ST:
00088 gtabs.st_tab_size = hdr.size / hdr.entsize;
00089 gtabs.st_tab = (ST *)addr;
00090 break;
00091
00092 case SHDR_TY:
00093 gtabs.ty_tab_size = hdr.size / hdr.entsize;
00094 gtabs.ty_tab = (TY *)addr;
00095 break;
00096
00097 case SHDR_PU:
00098 gtabs.pu_tab_size = hdr.size / hdr.entsize;
00099 gtabs.pu_tab = (PU *) addr;
00100 break;
00101
00102 case SHDR_FLD:
00103 gtabs.fld_tab_size = hdr.size / hdr.entsize;
00104 gtabs.fld_tab = (FLD *) addr;
00105 break;
00106
00107 case SHDR_ARB:
00108 gtabs.arb_tab_size = hdr.size / hdr.entsize;
00109 gtabs.arb_tab = (ARB *) addr;
00110 break;
00111
00112 case SHDR_TYLIST:
00113 gtabs.tylist_tab_size = hdr.size / hdr.entsize;
00114 gtabs.tylist_tab = (TYLIST *) addr;
00115 break;
00116
00117 case SHDR_TCON:
00118 gtabs.tcon_tab_size = hdr.size / hdr.entsize;
00119 gtabs.tcon_tab = (TCON *) addr;
00120 break;
00121
00122 case SHDR_STR:
00123 gtabs.tconstr_tab_size = hdr.size;
00124 gtabs.tconstr_tab = addr;
00125 break;
00126
00127 case SHDR_INITO:
00128 gtabs.inito_tab_size = hdr.size / hdr.entsize;
00129 gtabs.inito_tab = (INITO *) addr;
00130 break;
00131
00132 case SHDR_INITV:
00133 gtabs.initv_tab_size = hdr.size / hdr.entsize;
00134 gtabs.initv_tab = (INITV *) addr;
00135 break;
00136
00137 case SHDR_ST_ATTR:
00138 gtabs.st_attr_tab_size = hdr.size / hdr.entsize;
00139 gtabs.st_attr_tab = (ST_ATTR *) addr;
00140 break;
00141 }
00142 }
00143 }
00144
00145 #define DEFAULT_MAX_EXT_NUM (1024)
00146
00147 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
00148
00149 inline BOOL
00150 ST_is_weak_alias(const ST &st)
00151 {
00152 return (ST_is_weak_symbol(st) && ST_strong_idx(st) != ST_st_idx(st));
00153 }
00154
00155
00156 inline const ST &
00157 ST_alias_base(const ST &st, const IPC_GLOBAL_TABS >abs)
00158 {
00159 return gtabs.st_tab[ST_IDX_index(ST_strong_idx(st))];
00160 }
00161
00162 template <class Sym>
00163 static void
00164 enter_st (const IPC_GLOBAL_TABS >abs, const ST &st, Sym &esym)
00165 {
00166 INT type, binding;
00167
00168 esym.st_name = ST_name_idx (st);
00169
00170 ST_SCLASS sclass = ST_storage_class(st);
00171
00172 esym.st_value = (sclass == SCLASS_EXTERN) ? 0 : ST_ofst (st);
00173 esym.st_size = 0;
00174
00175 if (ST_is_weak_alias (st)) {
00176 const ST &alias_base = ST_alias_base(st, gtabs);
00177 sclass = ST_storage_class(alias_base);
00178 esym.st_value = (sclass == SCLASS_EXTERN) ? 0 : ST_ofst (alias_base);
00179 binding = STB_WEAK;
00180 } else if (ST_is_weak_symbol (st))
00181 binding = STB_WEAK;
00182 else
00183 binding = STB_GLOBAL;
00184
00185 switch (ST_sym_class (st)) {
00186 case CLASS_VAR:
00187 type = STT_OBJECT;
00188 esym.st_size = TY_size (gtabs.ty_tab[TY_IDX_index (ST_type (st))]);
00189 switch (sclass) {
00190 case SCLASS_EXTERN:
00191 esym.st_shndx = SHN_UNDEF;
00192 break;
00193 case SCLASS_COMMON:
00194 esym.st_shndx = SHN_COMMON;
00195 esym.st_value = TY_align (ST_type (st));
00196 break;
00197 default:
00198 esym.st_shndx = SHN_MIPS_DATA;
00199 break;
00200 }
00201 break;
00202 case CLASS_FUNC:
00203 type = STT_FUNC;
00204 esym.st_shndx = (sclass == SCLASS_EXTERN) ? SHN_UNDEF : SHN_MIPS_TEXT;
00205 break;
00206 default:
00207 type = STT_NOTYPE;
00208 esym.st_shndx = (sclass == SCLASS_EXTERN) ? SHN_UNDEF : SHN_MIPS_DATA;
00209 break;
00210 }
00211
00212 esym.st_info = ELF_ST_INFO (binding, type);
00213
00214 switch (ST_export(st)) {
00215 case EXPORT_INTERNAL:
00216 esym.st_other = STO_INTERNAL;
00217 break;
00218 case EXPORT_HIDDEN:
00219 esym.st_other = STO_HIDDEN;
00220 break;
00221 case EXPORT_PROTECTED:
00222 esym.st_other = STO_PROTECTED;
00223 break;
00224 case EXPORT_OPTIONAL:
00225 esym.st_other = STO_OPTIONAL;
00226 break;
00227 case EXPORT_PREEMPTIBLE:
00228 default:
00229 esym.st_other = STO_DEFAULT;
00230 break;
00231 }
00232
00233 }
00234
00235
00236 template <class Sym>
00237 static pair<Sym *, UINT>
00238 walk_st_list (const IPC_GLOBAL_TABS& gtabs, const Sym*)
00239 {
00240 UINT max_ext_num = DEFAULT_MAX_EXT_NUM;
00241 UINT size = 0;
00242 Sym *ext_symtab = (Sym *)
00243 MEM_POOL_Alloc (Malloc_Mem_Pool, sizeof(Sym) * max_ext_num);
00244
00245 for (UINT32 idx = 1; idx < gtabs.st_tab_size; idx++) {
00246 const ST &st = gtabs.st_tab[idx];
00247
00248 if (ST_export(st) != EXPORT_LOCAL &&
00249 ST_export(st) != EXPORT_LOCAL_INTERNAL) {
00250
00251 if (size >= max_ext_num) {
00252 ext_symtab = (Sym *)
00253 MEM_POOL_Realloc (Malloc_Mem_Pool, ext_symtab,
00254 sizeof(Sym) * max_ext_num,
00255 sizeof(Sym) * max_ext_num * 2);
00256 max_ext_num *= 2;
00257 }
00258 enter_st(gtabs, st, ext_symtab[size++]);
00259 }
00260 }
00261 return pair<Sym *, UINT> (ext_symtab, size);
00262 }
00263
00264
00265 static void
00266 check_revision (const char *base, UINT64 sh_size, const char* file_name)
00267 {
00268 const char* eob;
00269 static const char *revision = WHIRL_REVISION;
00270 int len = strlen (revision);
00271
00272 const char* p = base;
00273 eob = p + sh_size - 1;
00274
00275 if (*eob != 0)
00276
00277 ErrMsg (EC_IR_Scn_Read, ".comment", file_name);
00278
00279 while (p <= eob) {
00280 if (strncmp (p, revision, len) == 0)
00281 return;
00282 p += strlen (p) + 1;
00283 }
00284
00285 ErrMsg (EC_IR_Revision, base, file_name);
00286 }
00287
00288
00289
00290
00291 template <class Shdr, class Sym>
00292 void
00293 process_whirl (an_object_file_ptr p_obj, int nsec, const Shdr* section_table,
00294 BOOL check_whirl_revision, const char* file_name,
00295 const Sym* elf_symtab, off_t mmap_size)
00296 {
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 int i;
00313 int gsymtab_idx = 0;
00314 int strtab_idx = 0;
00315 int found_summary = 0;
00316 int pu_section_idx = 0;
00317
00318 if (ld_ipa_opt[LD_IPA_HIDES].flag == HS_DEFAULT)
00319 ld_ipa_opt[LD_IPA_HIDES].flag = HS_EXPORTS;
00320
00321 for (i = 1; i < nsec; i++) {
00322 if (check_whirl_revision &&
00323 section_table[i].sh_type == SHT_PROGBITS &&
00324 strcmp (ld_get_section_name (p_obj, i), ELF_COMMENT) == 0) {
00325
00326 read_one_section (i, p_obj);
00327 check_revision (ld_get_section_base (p_obj, i),
00328 section_table[i].sh_size, file_name);
00329 }
00330
00331 if (section_table[i].sh_type != SHT_MIPS_WHIRL)
00332 continue;
00333
00334 switch (section_table[i].sh_info) {
00335 case WT_GLOBALS:
00336 gsymtab_idx = i;
00337 break;
00338 case WT_STRTAB:
00339 strtab_idx = i;
00340 break;
00341 case WT_IPA_SUMMARY:
00342 found_summary = 1;
00343 break;
00344 case WT_PU_SECTION:
00345 pu_section_idx = i;
00346 break;
00347 default:
00348 break;
00349 }
00350 }
00351
00352 if (gsymtab_idx == 0 || strtab_idx == 0 || pu_section_idx == 0)
00353 ErrMsg (EC_IR_Scn_Read, "symbol table or pu_info", file_name);
00354
00355 if (!found_summary)
00356 ErrMsg (EC_IR_Scn_Read, "summary info", file_name);
00357
00358 Elf64_Word gsymtab_size = section_table[gsymtab_idx].sh_size;
00359 const GLOBAL_SYMTAB_HEADER_TABLE *gsymtab =
00360 (GLOBAL_SYMTAB_HEADER_TABLE *) ld_get_section_base (p_obj, gsymtab_idx);
00361
00362 if (gsymtab->size < sizeof(gsymtab) ||
00363 gsymtab->size > gsymtab_size ||
00364 gsymtab->entries < GLOBAL_SYMTAB_TABLES) {
00365 ErrMsg (EC_IR_Scn_Read, "global symbol table", file_name);
00366 }
00367
00368 for (i = 0; i < GLOBAL_SYMTAB_TABLES; ++i) {
00369 const SYMTAB_HEADER &hdr = gsymtab->header[i];
00370 if (hdr.offset + hdr.size > gsymtab_size)
00371 ErrMsg (EC_IR_Scn_Read, "global symbol table", file_name);
00372 }
00373
00374 IP_FILE_HDR &file_header =
00375 Setup_File_Header (file_name, ld_get_mmap_addr (p_obj), mmap_size);
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 IPC_GLOBAL_TABS gtabs;
00387
00388 gtabs.symstr_tab_size = ld_get_section_size (p_obj, strtab_idx);
00389 gtabs.symstr_tab = (char*) ld_get_section_base (p_obj, strtab_idx);
00390 get_global_symtab (gtabs, IP_FILE_HDR_file_info (file_header), p_obj,
00391 gsymtab);
00392 #if !defined(TARG_IA64) && !defined(TARG_X8664) && !defined(TARG_MIPS) && !defined(TARG_SL)
00393
00394 pair<Sym *, UINT> ext_symtab = walk_st_list (gtabs, elf_symtab);
00395
00396 if (ext_symtab.second > 0) {
00397 #if 1
00398 an_elf_sym_record *p_sym = (an_elf_sym_record *)ext_symtab.first;
00399 merge_ext (p_sym,
00400 #else
00401 merge_ext (reinterpret_cast<an_elf_sym_record *> (ext_symtab.first),
00402 #endif
00403 ld_get_section_base (p_obj, strtab_idx),
00404 ext_symtab.second, p_obj);
00405 }
00406
00407 MEM_POOL_FREE (Malloc_Mem_Pool, ext_symtab.first);
00408 #endif
00409
00410
00411
00412
00413
00414
00415
00416
00417 IPC_GLOBAL_IDX_MAP *idx_maps =
00418 IPC_merge_global_tab (gtabs, file_header,
00419 IP_FILE_HDR_mem_pool(file_header));
00420
00421 Set_IP_FILE_HDR_idx_maps (file_header, idx_maps);
00422
00423 ipa_insert_whirl_obj_marker ();
00424
00425 }
00426
00427
00428 static BOOL ipa_dot_so_initialized = FALSE;
00429
00430 #ifdef KEY
00431 #include "ipc_defs.h"
00432
00433 IP_TARGET_TYPE IPA_Target_Type;
00434 #endif
00435
00436 extern "C" void
00437 process_whirl32 (an_object_file_ptr p_obj, INT nsec,
00438 const Elf32_Shdr* section_table,
00439 BOOL check_whirl_revision, const char* file_name, off_t mmap_size)
00440 {
00441 if (!ipa_dot_so_initialized) {
00442 #ifdef KEY
00443 IPA_Target_Type = IP_32_bit_ABI;
00444 #endif
00445 ipa_dot_so_initialized = TRUE;
00446 ipa_dot_so_init ();
00447 }
00448
00449 Elf32_Sym *tag = 0;
00450 process_whirl (p_obj, nsec, section_table, check_whirl_revision,
00451 file_name, tag, mmap_size);
00452 }
00453
00454 extern "C" void
00455 process_whirl64 (an_object_file_ptr p_obj, INT nsec,
00456 const Elf64_Shdr* section_table,
00457 BOOL check_whirl_revision, const char* file_name, off_t mmap_size)
00458 {
00459 if (!ipa_dot_so_initialized) {
00460 #ifdef KEY
00461 IPA_Target_Type = IP_64_bit_ABI;
00462 #endif
00463 ipa_dot_so_initialized = TRUE;
00464 ipa_dot_so_init ();
00465 }
00466
00467 Elf64_Sym *tag = 0;
00468 process_whirl (p_obj, nsec, section_table, check_whirl_revision,
00469 file_name, tag, mmap_size);
00470 }
00471
00472 extern "C" void *
00473 ipa_open_input(char *name, off_t *p_size)
00474 {
00475 return WN_open_input(name,p_size);
00476 }
00477
00478 #else // _STANDALONE_INLINER
00479
00480 #include "ir_bread.h"
00481 void
00482 Process_Global_Symtab (void* handle, IP_FILE_HDR& file_header)
00483 {
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_GLOBALS);
00495 char *base = (char *) handle + shdr.offset;
00496
00497 const GLOBAL_SYMTAB_HEADER_TABLE *gsymtab =
00498 (GLOBAL_SYMTAB_HEADER_TABLE *) base;
00499
00500 IPC_GLOBAL_TABS gtabs;
00501
00502 shdr = get_section (handle, SHT_MIPS_WHIRL, WT_STRTAB);
00503 base = (char *) handle + shdr.offset;
00504 gtabs.symstr_tab_size = shdr.size;
00505 gtabs.symstr_tab = base;
00506 get_global_symtab (gtabs, IP_FILE_HDR_file_info (file_header), NULL,
00507 gsymtab);
00508
00509
00510
00511
00512
00513
00514
00515
00516 IPC_GLOBAL_IDX_MAP *idx_maps =
00517 IPC_merge_global_tab (gtabs, file_header,
00518 IP_FILE_HDR_mem_pool(file_header));
00519
00520 Set_IP_FILE_HDR_idx_maps (file_header, idx_maps);
00521
00522 }
00523
00524
00525 #endif // _STANDALONE_INLINER