Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 #ifdef USE_PCH 00037 #include "common_com_pch.h" 00038 #endif /* USE_PCH */ 00039 #pragma hdrstop 00040 #include <unistd.h> /* for unlink() */ 00041 #include <sys/mman.h> /* for mmap() */ 00042 #include <string.h> /* for strerror() */ 00043 #include <errno.h> /* for errno */ 00044 #include <elf.h> /* for all Elf stuff */ 00045 #include <sys/elf_whirl.h> /* for WHIRL sections' sh_info */ 00046 00047 // Solaric CC workaround 00048 // no big deal, just to fix a compiler warning 00049 #ifndef USE_STANDARD_TYPES 00050 #define USE_STANDARD_TYPES /* override unwanted defines in "defs.h" */ 00051 #endif 00052 00053 #include "defs.h" 00054 #include "alignof.h" /* for ALIGNOF() */ 00055 #include "erglob.h" 00056 #include "errors.h" /* for ErrMsg() */ 00057 #include "opcode.h" 00058 #include "mempool.h" 00059 #include "wn.h" 00060 #include "wn_map.h" 00061 #include "strtab.h" /* for strtab */ 00062 #include "symtab.h" /* for symtab */ 00063 #include "irbdata.h" /* for inito */ 00064 #define USE_DST_INTERNALS 00065 #include "dwarf_DST_mem.h" /* for dst */ 00066 #include "pu_info.h" 00067 #include "ir_bwrite.h" 00068 #include "ir_bcom.h" 00069 #include <vector> 00070 00071 /* For 4K page, each kernel page maps to 4Mbytes user address space */ 00072 #define MAPPED_SIZE 0x400000 00073 #define INIT_TMP_MAPPED_SIZE MAPPED_SIZE 00074 00075 #ifdef BACK_END 00076 #define DEFAULT_NUM_OF_PREFETCHES 64 00077 WN **prefetch_ldsts; 00078 INT num_prefetch_ldsts; 00079 INT max_num_prefetch_ldsts; 00080 00081 #define DEFAULT_NUM_ALIAS_CLASSES 128 00082 WN **alias_classes; 00083 INT num_alias_class_nodes; 00084 INT max_alias_class_nodes; 00085 00086 #define DEFAULT_NUM_AC_INTERNALS 128 00087 WN **ac_internals; 00088 INT num_ac_internal_nodes; 00089 INT max_ac_internal_nodes; 00090 #endif 00091 00092 00093 char *Whirl_Revision = WHIRL_REVISION; 00094 00095 /* This variable is used by IPAA to pass its local map information 00096 * to ir_bwrite.c, and by ir_bread.c to pass it to WOPT: 00097 */ 00098 void *IPAA_Local_Map = NULL; 00099 00100 BOOL Doing_mmapped_io = FALSE; 00101 00102 /* copy a block of memory into the temporary file. 00103 * "align" is the alignment requirement, which must be a power of 2. 00104 * "padding" is the byte offset from the beginning of the buffer that the 00105 * alignment requirement applies. 00106 * 00107 * It returns the file offset corresponding to buf + padding. 00108 */ 00109 extern Elf64_Word 00110 ir_b_save_buf (const void *buf, Elf64_Word size, unsigned int align, 00111 unsigned int padding, Output_File *fl) 00112 { 00113 Current_Output = fl; 00114 00115 off_t file_size = ir_b_align (fl->file_size, align, padding); 00116 00117 if (file_size + size >= fl->mapped_size) 00118 ir_b_grow_map (file_size + size - fl->file_size, fl); 00119 00120 Doing_mmapped_io = TRUE; 00121 (void *)memcpy(fl->map_addr + file_size, buf, size); 00122 Doing_mmapped_io = FALSE; 00123 00124 fl->file_size = file_size + size; 00125 return file_size + padding; 00126 } /* ir_b_save_buf */ 00127 00128 /* copy a file into the temporary file. 00129 */ 00130 extern Elf64_Word 00131 ir_b_copy_file (const void *buf, Elf64_Word size, void *tmpfl) 00132 { 00133 Output_File* fl = (Output_File*)tmpfl; 00134 00135 Current_Output = fl; 00136 00137 if (size >= fl->mapped_size) 00138 ir_b_grow_map (size, fl); 00139 00140 Doing_mmapped_io = TRUE; 00141 memcpy (fl->map_addr, buf, size); 00142 Doing_mmapped_io = FALSE; 00143 fl->file_size = size; 00144 return size; 00145 } // ir_b_copy_file 00146 00147 00148 static void 00149 save_buf_at_offset (const void *buf, Elf64_Word size, off_t offset, 00150 Output_File *fl) 00151 { 00152 Is_True (offset + size <= fl->mapped_size, ("Invalid buffer size")); 00153 00154 Doing_mmapped_io = TRUE; 00155 memcpy (fl->map_addr + offset, buf, size); 00156 Doing_mmapped_io = FALSE; 00157 } // save_buf_at_offset 00158 00159 // similar to ir_b_save_buf, except that no actual copying is done, but 00160 // file space is reserved. 00161 static Elf64_Word 00162 ir_b_reserve_space (Elf64_Word size, unsigned int align, Output_File *fl) 00163 { 00164 off_t file_size = ir_b_align (fl->file_size, align, 0); 00165 00166 if (file_size + size >= fl->mapped_size) 00167 ir_b_grow_map (file_size + size - fl->file_size, fl); 00168 00169 fl->file_size = file_size + size; 00170 return file_size; 00171 } // ir_b_reserve_space 00172 00173 00174 /* increase the mmap size. It is faster if we first unmap the region and 00175 * then map it again with a larger size. The overhead for maintaining 00176 * multiple regions (by the kernel) outweighs that of extra system calls. 00177 * Also, we get a contiguous address space for the file this way. 00178 */ 00179 char * 00180 ir_b_grow_map (Elf64_Word min_size, Output_File *fl) 00181 { 00182 Is_True (fl->map_addr != 0, ("output file not yet mapped")); 00183 00184 if (munmap (fl->map_addr, fl->mapped_size) == -1) 00185 ErrMsg (EC_IR_Write, fl->file_name, errno); 00186 min_size += fl->file_size; 00187 while (fl->mapped_size < min_size) { 00188 if (fl->mapped_size < MAPPED_SIZE) 00189 fl->mapped_size = MAPPED_SIZE; 00190 else 00191 fl->mapped_size += MAPPED_SIZE; 00192 } 00193 00194 #if defined(__sgi) 00195 // Only SGI supports 'MAP_AUTOGROW' for mmap() 00196 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE, 00197 MAP_SHARED|MAP_AUTOGROW, fl->output_fd, 0); 00198 #else 00199 // mmap() normally cannot automatically increase file size, so we 00200 // allocate some space using ftruncate(). SGI's mmap() can avoid 00201 // this. cf. use of ftruncate() in ir_bwrite.cxx. 00202 if (ftruncate(fl->output_fd, fl->mapped_size)) { 00203 ErrMsg (EC_IR_Write, fl->file_name, strerror(errno)); 00204 } 00205 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE, 00206 MAP_SHARED, fl->output_fd, 0); 00207 #endif 00208 00209 if (fl->map_addr == (char *) (-1)) 00210 ErrMsg (EC_IR_Write, fl->file_name, strerror(errno)); 00211 00212 return fl->map_addr; 00213 } /* ir_b_grow_map */ 00214 00215 extern char * 00216 ir_b_create_map (Output_File *fl) 00217 { 00218 int fd = fl->output_fd; 00219 fl->mapped_size = INIT_TMP_MAPPED_SIZE; 00220 00221 #if defined(__sgi) 00222 // Only SGI supports 'MAP_AUTOGROW' for mmap() 00223 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE, 00224 MAP_SHARED|MAP_AUTOGROW, fl->output_fd, 0); 00225 #else 00226 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE, 00227 MAP_SHARED, fl->output_fd, 0); 00228 #endif 00229 00230 return fl->map_addr; 00231 } /* ir_b_create_map */ 00232 00233 00234 WN *staticNode; 00235 00236 /* Walk the tree and copy it to contiguous memory block in the temp. file */ 00237 extern Elf64_Word 00238 ir_b_write_tree (WN *node, off_t base_offset, Output_File *fl, WN_MAP off_map) 00239 { 00240 register OPCODE opcode; 00241 Elf64_Word node_offset; 00242 char *real_addr; 00243 00244 if (node == staticNode) abort(); 00245 00246 INT32 size = WN_Size_and_StartAddress (node, (void **) &real_addr); 00247 00248 #define WN_ADDR(offset) ((WN *)(fl->map_addr + offset)) 00249 00250 node_offset = ir_b_save_buf (real_addr, size, ALIGNOF(WN), 00251 (char *)(node) - real_addr, fl); 00252 00253 opcode = (OPCODE) WN_opcode (node); 00254 00255 #ifdef BACK_END 00256 if (off_map != WN_MAP_UNDEFINED && 00257 (Write_BE_Maps || 00258 Write_ALIAS_CLASS_Map || 00259 Write_AC_INTERNAL_Map)) { 00260 /* save node_offset for use when writing maps */ 00261 BOOL set_offset = FALSE; 00262 OPERATOR opr = OPCODE_operator(opcode); 00263 00264 if (Write_BE_Maps) { 00265 if (opr == OPR_PREFETCH || opr == OPR_PREFETCHX || 00266 OPCODE_is_load (opcode) || OPCODE_is_store (opcode)) 00267 set_offset = TRUE; 00268 00269 /* check if the WN has a prefetch pointer */ 00270 if (WN_MAP_Get(WN_MAP_PREFETCH, node)) { 00271 /* make sure the prefetch_ldsts array is big enough to hold the 00272 lds and sts plus one extra slot to mark the end */ 00273 if (num_prefetch_ldsts == 0) { 00274 max_num_prefetch_ldsts = DEFAULT_NUM_OF_PREFETCHES; 00275 prefetch_ldsts = 00276 (WN **)malloc(max_num_prefetch_ldsts * sizeof(WN*)); 00277 FmtAssert (prefetch_ldsts, 00278 ("No more memory for allocation.")); 00279 } else if (max_num_prefetch_ldsts == num_prefetch_ldsts + 1) { 00280 max_num_prefetch_ldsts *= 2; 00281 prefetch_ldsts = 00282 (WN **)realloc(prefetch_ldsts, 00283 max_num_prefetch_ldsts * sizeof(WN*)); 00284 FmtAssert (prefetch_ldsts, 00285 ("No more memory for allocation.")); 00286 } 00287 prefetch_ldsts[num_prefetch_ldsts] = node; 00288 num_prefetch_ldsts += 1; 00289 } 00290 } 00291 00292 if (Write_ALIAS_CLASS_Map) { 00293 if (OPCODE_is_store (opcode) || 00294 OPCODE_is_load (opcode) || 00295 (opr == OPR_LDA /* && LDA_has_ac_map_set(node) */) || 00296 opr == OPR_PARM) { 00297 set_offset = TRUE; 00298 } 00299 00300 if (WN_MAP32_Get (WN_MAP_ALIAS_CLASS, node) != 0) { 00301 if (alias_classes == NULL) { 00302 max_alias_class_nodes = DEFAULT_NUM_ALIAS_CLASSES; 00303 alias_classes = (WN **) malloc (max_alias_class_nodes * 00304 sizeof(WN *)); 00305 FmtAssert (alias_classes != NULL, ("No more memory.")); 00306 } else if (max_alias_class_nodes == num_alias_class_nodes + 1) { 00307 max_alias_class_nodes *= 2; 00308 alias_classes = (WN **) realloc(alias_classes, 00309 max_alias_class_nodes * 00310 sizeof(WN **)); 00311 FmtAssert(alias_classes != NULL, ("No more memory.")); 00312 } 00313 alias_classes[num_alias_class_nodes++] = node; 00314 } 00315 } 00316 00317 if (Write_AC_INTERNAL_Map) { 00318 if (opr == OPR_ILOAD || 00319 opr == OPR_MLOAD || 00320 opr == OPR_PARM || 00321 opr == OPR_ISTORE || 00322 opr == OPR_PSTORE || 00323 opr == OPR_MSTORE) { 00324 set_offset = TRUE; 00325 } 00326 00327 if (WN_MAP_Get (WN_MAP_AC_INTERNAL, node) != NULL) { 00328 if (ac_internals == NULL) { 00329 max_ac_internal_nodes = DEFAULT_NUM_AC_INTERNALS; 00330 ac_internals = (WN **) malloc (max_ac_internal_nodes * 00331 sizeof(WN *)); 00332 FmtAssert (ac_internals != NULL, ("No more memory.")); 00333 } else if (max_ac_internal_nodes == num_ac_internal_nodes + 1) { 00334 max_ac_internal_nodes *= 2; 00335 ac_internals = (WN **) realloc(ac_internals, 00336 max_ac_internal_nodes * 00337 sizeof(WN **)); 00338 FmtAssert(ac_internals != NULL, ("No more memory.")); 00339 } 00340 ac_internals[num_ac_internal_nodes++] = node; 00341 } 00342 } 00343 00344 if (set_offset) 00345 WN_MAP32_Set(off_map, node, node_offset - base_offset); 00346 00347 } 00348 #endif /* BACK_END */ 00349 00350 00351 if (opcode == OPC_BLOCK) { 00352 register Elf64_Word prev, this_node; 00353 00354 if (WN_first(node) == 0) { 00355 WN_first(WN_ADDR(node_offset)) = (WN *) -1; 00356 WN_last(WN_ADDR(node_offset)) = (WN *) -1; 00357 } else { 00358 register WN *wn = WN_first (node); 00359 prev = ir_b_write_tree(wn, base_offset, fl, off_map); 00360 WN_first(WN_ADDR(node_offset)) = (WN *) prev; 00361 00362 while (wn = WN_next(wn)) { 00363 this_node = ir_b_write_tree(wn, base_offset, fl, off_map); 00364 /* fill in the correct next/prev offsets (in place of -1) */ 00365 WN_next(WN_ADDR(prev + base_offset)) = (WN *) this_node; 00366 WN_prev(WN_ADDR(this_node + base_offset)) = (WN *) prev; 00367 prev = this_node; 00368 } 00369 00370 WN_last(WN_ADDR(node_offset)) = (WN *) prev; 00371 } 00372 } else if (!OPCODE_is_leaf(opcode)) { 00373 register int i; 00374 00375 for (i = 0; i < WN_kid_count(node); i++) { 00376 register Elf64_Word kid; 00377 00378 if (WN_kid(node, i) == 0) { 00379 WN_kid(WN_ADDR(node_offset), i) = (WN *) -1; 00380 } else { 00381 kid = ir_b_write_tree (WN_kid(node, i), base_offset, 00382 fl, off_map); 00383 WN_kid(WN_ADDR(node_offset), i) = (WN *) kid; 00384 } 00385 } 00386 } 00387 00388 if (OPCODE_has_next_prev(opcode)) { 00389 /* just set the default values for now */ 00390 WN_prev(WN_ADDR(node_offset)) = (WN *) -1; 00391 WN_next(WN_ADDR(node_offset)) = (WN *) -1; 00392 } 00393 00394 return node_offset - base_offset; 00395 } /* ir_b_write_tree */ 00396 00397 00398 /*------------ symtab routines ---------------*/ 00399 00400 // function object for writing out various symbol tables 00401 template <class T> 00402 struct WRITE_TABLE_OP 00403 { 00404 Output_File *fl; 00405 00406 void operator () (UINT, T *t, UINT size) const { 00407 (void) ir_b_save_buf (t, size * sizeof(T), ALIGNOF(T), 0, fl); 00408 } 00409 00410 WRITE_TABLE_OP (Output_File *_fl) : fl (_fl) {} 00411 }; // WRITE_TABLE_OP 00412 00413 00414 template <class TABLE> 00415 Elf64_Word 00416 write_table (TABLE& fld, off_t base_offset, 00417 Output_File *fl) 00418 { 00419 off_t cur_offset = ir_b_align (fl->file_size, 00420 ALIGNOF(typename TABLE::base_type), 0); 00421 fl->file_size = ir_b_align (fl->file_size, 00422 ALIGNOF(typename TABLE::base_type), 0); 00423 00424 const WRITE_TABLE_OP<typename TABLE::base_type> write_table_op(fl); 00425 00426 For_all_blocks (fld, write_table_op); 00427 return cur_offset - base_offset; 00428 } // write_table 00429 00430 00431 static Elf64_Word 00432 write_file_info (off_t base_offset, Output_File *fl) 00433 { 00434 off_t cur_offset = ir_b_align (fl->file_size, ALIGNOF(FILE_INFO), 0); 00435 00436 ir_b_save_buf (&File_info, sizeof(File_info), ALIGNOF(FILE_INFO), 0, fl); 00437 00438 return cur_offset - base_offset; 00439 } // write_file_info 00440 00441 00442 // write a global symtab: 00443 Elf64_Word 00444 ir_b_write_global_symtab (off_t base_offset, Output_File *fl) 00445 { 00446 GLOBAL_SYMTAB_HEADER_TABLE gsymtab; 00447 00448 // should use __builtin_alignof(gsymtab) instead of sizeof(mUINT64), 00449 // but our frontend has a bug and fails to compile it. 00450 const Elf64_Word symtab_offset = 00451 ir_b_reserve_space (sizeof(gsymtab), sizeof(mUINT64), fl); 00452 00453 Elf64_Word cur_offset; 00454 UINT i = 0; 00455 const UINT idx = GLOBAL_SYMTAB; 00456 00457 cur_offset = write_file_info (symtab_offset, fl); 00458 gsymtab.header[i++].Init (cur_offset, sizeof(FILE_INFO), 00459 sizeof(FILE_INFO), ALIGNOF(FILE_INFO), 00460 SHDR_FILE); 00461 00462 cur_offset = write_table (*(Scope_tab[idx].st_tab), symtab_offset, fl); 00463 gsymtab.header[i++].Init (cur_offset, 00464 Scope_tab[idx].st_tab->Size () * sizeof(ST), 00465 sizeof(ST), ALIGNOF(ST), SHDR_ST); 00466 00467 // call fix_array_ty? 00468 00469 cur_offset = write_table (Ty_tab, symtab_offset, fl); 00470 gsymtab.header[i++].Init (cur_offset, Ty_tab.Size () * sizeof(TY), 00471 sizeof(TY), ALIGNOF(TY), SHDR_TY); 00472 00473 cur_offset = write_table (Pu_Table, symtab_offset, fl); 00474 gsymtab.header[i++].Init (cur_offset, Pu_Table.Size () * sizeof(PU), 00475 sizeof(PU), ALIGNOF(PU), SHDR_PU); 00476 00477 cur_offset = write_table (Fld_Table, symtab_offset, fl); 00478 gsymtab.header[i++].Init (cur_offset, Fld_Table.Size () * sizeof(FLD), 00479 sizeof(FLD), ALIGNOF(FLD), SHDR_FLD); 00480 00481 cur_offset = write_table (Arb_Table, symtab_offset, fl); 00482 gsymtab.header[i++].Init (cur_offset, Arb_Table.Size () * sizeof(ARB), 00483 sizeof(ARB), ALIGNOF(ARB), SHDR_ARB); 00484 00485 cur_offset = write_table (Tylist_Table, symtab_offset, fl); 00486 gsymtab.header[i++].Init (cur_offset, 00487 Tylist_Table.Size () * sizeof(TYLIST), 00488 sizeof(TYLIST), ALIGNOF(TYLIST), SHDR_TYLIST); 00489 00490 cur_offset = write_table (Tcon_Table, symtab_offset, fl); 00491 gsymtab.header[i++].Init (cur_offset, Tcon_Table.Size () * sizeof(TCON), 00492 sizeof(TCON), ALIGNOF(TCON), SHDR_TCON); 00493 00494 cur_offset = ir_b_save_buf (TCON_strtab_buffer (), TCON_strtab_size (), 00495 1, 0, fl) - symtab_offset; 00496 gsymtab.header[i++].Init (cur_offset, TCON_strtab_size (), 1, 1, SHDR_STR); 00497 00498 cur_offset = write_table (*(Scope_tab[idx].inito_tab), symtab_offset, fl); 00499 gsymtab.header[i++].Init (cur_offset, 00500 Scope_tab[idx].inito_tab->Size () * sizeof(INITO), 00501 sizeof(INITO), ALIGNOF(INITO), SHDR_INITO); 00502 00503 cur_offset = write_table (Initv_Table, symtab_offset, fl); 00504 gsymtab.header[i++].Init (cur_offset, Initv_Table.Size () * sizeof(INITV), 00505 sizeof(INITV), ALIGNOF(INITV), SHDR_INITV); 00506 00507 cur_offset = write_table (Blk_Table, symtab_offset, fl); 00508 gsymtab.header[i++].Init (cur_offset, Blk_Table.Size () * sizeof(BLK), 00509 sizeof(BLK), ALIGNOF(BLK), SHDR_BLK); 00510 00511 cur_offset = write_table (*(Scope_tab[idx].st_attr_tab), symtab_offset, fl); 00512 gsymtab.header[i++].Init (cur_offset, 00513 Scope_tab[idx].st_attr_tab->Size () * sizeof(ST_ATTR), 00514 sizeof(ST_ATTR), ALIGNOF(ST_ATTR), SHDR_ST_ATTR); 00515 00516 save_buf_at_offset (&gsymtab, sizeof(gsymtab), symtab_offset, fl); 00517 00518 return symtab_offset - base_offset; 00519 00520 } // ir_b_write_global_symtab 00521 00522 Elf64_Word 00523 ir_b_write_local_symtab (const SCOPE& pu, off_t base_offset, Output_File *fl) 00524 { 00525 00526 LOCAL_SYMTAB_HEADER_TABLE symtab; 00527 00528 const Elf64_Word symtab_offset = 00529 ir_b_reserve_space (sizeof(symtab), sizeof(mUINT64), fl); 00530 00531 UINT i = 0; 00532 Elf64_Word cur_offset; 00533 cur_offset = write_table (*pu.st_tab, symtab_offset, fl); 00534 symtab.header[i++].Init (cur_offset, pu.st_tab->Size () * sizeof(ST), 00535 sizeof(ST), ALIGNOF(ST), SHDR_ST); 00536 00537 cur_offset = write_table (*pu.label_tab, symtab_offset, fl); 00538 symtab.header[i++].Init (cur_offset, pu.label_tab->Size () * sizeof(LABEL), 00539 sizeof(LABEL), ALIGNOF(LABEL), SHDR_LABEL); 00540 00541 cur_offset = write_table (*pu.preg_tab, symtab_offset, fl); 00542 symtab.header[i++].Init (cur_offset, pu.preg_tab->Size () * sizeof(PREG), 00543 sizeof(PREG), ALIGNOF(PREG), SHDR_PREG); 00544 00545 cur_offset = write_table (*pu.inito_tab, symtab_offset, fl); 00546 symtab.header[i++].Init (cur_offset, pu.inito_tab->Size () * sizeof(INITO), 00547 sizeof(INITO), ALIGNOF(INITO), SHDR_INITO); 00548 00549 cur_offset = write_table (*pu.st_attr_tab, symtab_offset, fl); 00550 symtab.header[i++].Init (cur_offset, pu.st_attr_tab->Size () * sizeof(ST_ATTR), 00551 sizeof(ST_ATTR), ALIGNOF(ST_ATTR), SHDR_ST_ATTR); 00552 00553 save_buf_at_offset (&symtab, sizeof(symtab), symtab_offset, fl); 00554 00555 return symtab_offset - base_offset; 00556 00557 } // ir_b_write_local_symtab 00558 00559 00560 /* write blocks of data, then block headers, then # blocks */ 00561 extern Elf64_Word 00562 ir_b_write_dst (DST_TYPE dst, off_t base_offset, Output_File *fl) 00563 { 00564 vector<char *> savedOffsets; 00565 Elf64_Word cur_offset; 00566 DST_BLOCK_IDX i; 00567 block_header *dst_blocks; 00568 Current_DST = dst; 00569 00570 dst_blocks = ((DST_Type *)dst)->dst_blocks; 00571 FOREACH_DST_BLOCK(i) { 00572 /* may have 64-bit data fields, so align at 8 bytes */ 00573 savedOffsets.push_back(dst_blocks[i].offset); 00574 cur_offset = ir_b_save_buf (dst_blocks[i].offset, 00575 dst_blocks[i].size, ALIGNOF(INT64), 0, fl); 00576 dst_blocks[i].offset = (char*)(cur_offset - base_offset); 00577 } 00578 FOREACH_DST_BLOCK(i) { 00579 cur_offset = ir_b_save_buf 00580 ((char*)&dst_blocks[i], sizeof(block_header), 00581 ALIGNOF(block_header), 0, fl); 00582 } 00583 cur_offset = ir_b_save_buf 00584 ((char*)&((DST_Type *)dst)->last_block_header, sizeof(mINT32), 00585 ALIGNOF(INT32), 0, fl); 00586 00587 00588 // restore dst_blocks offsets 00589 FOREACH_DST_BLOCK(i) { 00590 dst_blocks[i].offset = savedOffsets[i]; 00591 } 00592 00593 return cur_offset - base_offset; 00594 } 00595 00596 00597