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 _KEEP_RCS_ID 00037 static const char source_file[] = __FILE__; 00038 #endif 00039 00040 #include <stdio.h> 00041 00042 #include <elf.h> 00043 #include <libelf.h> 00044 00045 #define USE_STANDARD_TYPES 1 00046 #include "defs.h" 00047 #include "erglob.h" 00048 #include "srcpos.h" 00049 #include "em_elf.h" 00050 #include "em_dwarf.h" 00051 #include "config_elf_targ.h" 00052 #include "targ_em_dwarf.h" 00053 00054 00055 INT data_alignment_factor; 00056 00057 static Dwarf_P_Debug dw_dbg; 00058 static Dwarf_Error dw_error; 00059 00060 #define MAX_DWARF_SECTIONS 20 00061 static pSCNINFO dwarf_scn[MAX_DWARF_SECTIONS]; 00062 static size_t num_dwarf_scns = 0; 00063 /* Allocate only one cie for the whole file. */ 00064 static Dwarf_Unsigned cie_index; 00065 00066 typedef struct { 00067 UINT16 dwarf_idx; 00068 char *path; 00069 } INCL; 00070 00071 typedef struct { 00072 UINT16 dwarf_idx; 00073 UINT16 incl_idx; 00074 char *filename; 00075 } FNAME; 00076 00077 static INCL *incl_table; 00078 static INT incl_table_size; 00079 static FNAME *file_table; 00080 static INT file_table_size; 00081 00082 static void 00083 identity_function(Dwarf_Unsigned symidx, 00084 Dwarf_Unsigned *elf_symidx, 00085 Dwarf_Unsigned *elf_symoff) 00086 { 00087 *elf_symidx = symidx; 00088 *elf_symoff = 0; 00089 } 00090 00091 static Dwarf_Unsigned 00092 another_identity_function(Elf64_Word x) 00093 { 00094 return x; 00095 } 00096 00097 static symbol_index_recorder Record_Symidx; 00098 00099 static int /* TODO: should be size_t */ 00100 setup_new_section_for_dwarf ( 00101 char *name, 00102 int is_64bit, 00103 Dwarf_Unsigned type, 00104 Dwarf_Unsigned flags, 00105 Dwarf_Unsigned link, 00106 Dwarf_Unsigned info, 00107 Dwarf_Unsigned *name_idx, 00108 int *error) 00109 { 00110 pSCNINFO newscn; 00111 BOOL is_reloc; 00112 INT scnalign; 00113 00114 if (num_dwarf_scns >= MAX_DWARF_SECTIONS) { 00115 fprintf (stderr, "ERROR: setup_new_section_for_dwarf: too many dwarf sections\n"); 00116 exit(-1); 00117 } 00118 00119 is_reloc = (type == SHT_REL) || (type == SHT_RELA); 00120 scnalign = (is_reloc) ? (is_64bit ? ELF64_FSZ_XWORD : ELF32_FSZ_WORD) : 1; 00121 newscn = Em_New_Section (name, type, flags, 0, scnalign); 00122 00123 /* For relocation sections, we need to setup the link field to the 00124 symbol table section index. The dwarf producer does not know about 00125 this. 00126 */ 00127 if (is_reloc) { 00128 Em_Set_sh_link (newscn, Em_Get_Section_Index (Symtab_Info)); 00129 } 00130 else { 00131 Em_Set_sh_link (newscn, link); 00132 } 00133 Em_Set_sh_info (newscn, info); 00134 dwarf_scn[num_dwarf_scns] = newscn; 00135 num_dwarf_scns++; 00136 *name_idx = (Dwarf_Unsigned) Record_Symidx(Em_Create_Section_Symbol(newscn)); 00137 return Em_Get_Section_Index (newscn); 00138 } 00139 00140 pSCNINFO 00141 Em_Dwarf_Find_Dwarf_Scn (size_t scndx) 00142 { 00143 size_t i; 00144 00145 for (i = 0; i < num_dwarf_scns; i++) { 00146 if (Em_Get_Section_Index (dwarf_scn[i]) == scndx) return dwarf_scn[i]; 00147 } 00148 return NULL; 00149 } 00150 00151 pSCNINFO 00152 Em_Dwarf_Find_Dwarf_Scn_By_Name (char *name) 00153 { 00154 size_t i; 00155 char *scnname; 00156 00157 for (i = 0; i < num_dwarf_scns; i++) { 00158 scnname = Em_Get_Section_Name(dwarf_scn[i]); 00159 if (0 == strcmp(scnname, name)) return dwarf_scn[i]; 00160 } 00161 return NULL; 00162 } 00163 00164 00165 00166 static void 00167 Increase_Incl_Table_Size (UINT16 incl_idx) 00168 { 00169 UINT16 new_idx; 00170 00171 /* realloc incl_table if needed */ 00172 if (incl_idx >= incl_table_size) { 00173 new_idx = incl_idx + 5; 00174 if (incl_table == NULL) { 00175 incl_table = (INCL *) malloc (new_idx * sizeof (INCL)); 00176 } 00177 else { 00178 incl_table = (INCL *) realloc (incl_table, new_idx * sizeof(INCL)); 00179 } 00180 if (incl_table == NULL) { 00181 ErrMsg ( EC_No_Mem, "Increase_Incl_Table_Size" ); 00182 } 00183 bzero (&incl_table[incl_table_size], new_idx - incl_table_size); 00184 incl_table_size = new_idx; 00185 } 00186 } 00187 00188 void 00189 Em_Dwarf_Add_Include (UINT16 incl_idx, char *name) 00190 { 00191 Dwarf_Unsigned dwarf_idx; 00192 00193 Increase_Incl_Table_Size (incl_idx); 00194 dwarf_idx = dwarf_add_directory_decl (dw_dbg, name, &dw_error); 00195 incl_table[incl_idx].dwarf_idx = dwarf_idx; 00196 incl_table[incl_idx].path = name; 00197 } 00198 00199 00200 static void 00201 Increase_File_Table_Size (UINT16 file_idx) 00202 { 00203 UINT16 new_idx; 00204 00205 /* realloc file_table if needed */ 00206 if (file_idx >= file_table_size) { 00207 new_idx = file_idx + 5; 00208 if (file_table == NULL) { 00209 file_table = (FNAME *) malloc (new_idx * sizeof (FNAME)); 00210 } 00211 else { 00212 file_table = (FNAME *) realloc (file_table, new_idx * sizeof(FNAME)); 00213 } 00214 if (file_table == NULL) { 00215 ErrMsg ( EC_No_Mem, "Increase_File_Table_Size" ); 00216 } 00217 bzero (&file_table[file_table_size], new_idx - file_table_size); 00218 file_table_size = new_idx; 00219 } 00220 } 00221 00222 00223 void 00224 Em_Dwarf_Add_File ( 00225 UINT16 file_idx, 00226 char *name, 00227 UINT16 incl_idx, 00228 Dwarf_Unsigned modification_time, 00229 Dwarf_Unsigned file_size) 00230 { 00231 Dwarf_Unsigned dwarf_idx; 00232 00233 Increase_File_Table_Size (file_idx); 00234 dwarf_idx = dwarf_add_file_decl ( 00235 dw_dbg, 00236 name, 00237 incl_table[incl_idx].dwarf_idx, 00238 modification_time, 00239 file_size, 00240 &dw_error); 00241 file_table[file_idx].dwarf_idx = dwarf_idx; 00242 file_table[file_idx].filename = name; 00243 file_table[file_idx].incl_idx = incl_idx; 00244 } 00245 00246 00247 Dwarf_P_Debug 00248 Em_Dwarf_Begin (BOOL is_64bit, BOOL dwarf_trace, BOOL is_cplus, 00249 symbol_index_recorder record_symidx) 00250 { 00251 Dwarf_Unsigned flags; 00252 char *augmenter; 00253 #define EXT_OP(v) (DW_CFA_extended | v) 00254 static unsigned char init_bytes[] = TARG_INIT_BYTES; 00255 00256 if (record_symidx == NULL) { 00257 record_symidx = another_identity_function; 00258 } 00259 00260 Record_Symidx = record_symidx; 00261 00262 /* Initialize the incl_table and file_table to contain entries for index 0 */ 00263 Increase_Incl_Table_Size (0); 00264 Increase_File_Table_Size (0); 00265 00266 data_alignment_factor = is_64bit ? -8 : -4; 00267 flags = DW_DLC_WRITE | ((is_64bit) ? DW_DLC_SIZE_64 : DW_DLC_SIZE_32); 00268 flags |= DWARF_TARGET_FLAG; 00269 flags |= DW_DLC_SYMBOLIC_RELOCATIONS; 00270 dw_dbg = dwarf_producer_init_b (flags, setup_new_section_for_dwarf, 00271 0, 0, &dw_error); 00272 00273 if (is_cplus) /* may have eh info */ 00274 augmenter = DW_CIE_AUGMENTER_STRING_V0; 00275 else 00276 augmenter = ""; 00277 cie_index = dwarf_add_frame_cie (dw_dbg, augmenter, 00278 4, data_alignment_factor, 00279 DW_FRAME_RA_COL, 00280 init_bytes, sizeof(init_bytes), &dw_error); 00281 00282 return dw_dbg; 00283 } 00284 00285 extern "C" Dwarf_P_Debug 00286 Em_Dwarf_Begin (BOOL is_64bit, BOOL dwarf_trace, BOOL is_cplus) 00287 { 00288 return Em_Dwarf_Begin(is_64bit, dwarf_trace, is_cplus, NULL); 00289 } 00290 00291 static Dwarf_Signed section_count = DW_DLV_NOCOUNT; 00292 static Dwarf_Unsigned relocation_section_count = DW_DLV_NOCOUNT; 00293 00294 struct index_to_buffer_map_entry { 00295 pSCNINFO cursection; 00296 Dwarf_Signed scndx; 00297 Dwarf_Ptr buffer; 00298 Dwarf_Unsigned bufsize; 00299 }; 00300 00301 index_to_buffer_map_entry *index_to_buffer_map; 00302 00303 static inline int 00304 find_indexed_section( int i, 00305 const Dwarf_Signed scn) 00306 { 00307 for (; i < section_count; ++i) { 00308 if (index_to_buffer_map[i].scndx == scn) { 00309 return i; 00310 } 00311 } 00312 return -1; 00313 } 00314 00315 static int current_scn; 00316 00317 static int 00318 advance_to_next_stream_buffer(const Dwarf_Signed scndx) 00319 { 00320 if (current_scn >= section_count) { 00321 fprintf(stderr, "Too many calls to advance_to_next_stream_buffer"); 00322 exit(-1); 00323 } 00324 current_scn = 00325 find_indexed_section(current_scn + 1, scndx); 00326 return current_scn != -1; 00327 } 00328 00329 static Dwarf_Ptr 00330 get_current_buffer(void) 00331 { 00332 return index_to_buffer_map[current_scn].buffer; 00333 } 00334 00335 static Dwarf_Unsigned 00336 get_current_bufsize(void) 00337 { 00338 return index_to_buffer_map[current_scn].bufsize; 00339 } 00340 00341 void 00342 Em_Dwarf_Write_Scns (Cg_Dwarf_Sym_To_Elfsym_Ofst translate_dwarf_sym) 00343 { 00344 Dwarf_Signed i; 00345 Dwarf_Ptr buffer; 00346 Dwarf_Signed scndx; 00347 Dwarf_Unsigned bufsize; 00348 int result; 00349 int reloc_buffer_version; 00350 pSCNINFO cursection; 00351 00352 if (translate_dwarf_sym == NULL) { 00353 translate_dwarf_sym = identity_function; 00354 } 00355 00356 index_to_buffer_map = 00357 (index_to_buffer_map_entry *) malloc(section_count * 00358 sizeof(index_to_buffer_map_entry)); 00359 00360 dwarf_reset_section_bytes(dw_dbg); 00361 00362 for (i = 0; i < section_count; i++) { 00363 buffer = dwarf_get_section_bytes (dw_dbg, i, &scndx, &bufsize, &dw_error); 00364 cursection = Em_Dwarf_Find_Dwarf_Scn (scndx); 00365 if (cursection != NULL) { 00366 index_to_buffer_map[i].cursection = cursection; 00367 index_to_buffer_map[i].scndx = scndx; 00368 index_to_buffer_map[i].buffer = buffer; 00369 index_to_buffer_map[i].bufsize = bufsize; 00370 } 00371 else { 00372 fprintf (stderr, "ERROR No such section index: %d\n", (int)scndx); 00373 exit(-1); 00374 } 00375 } 00376 00377 // Now get the relocation buffers, translate each one into an ELF 00378 // relocation section, and write the ELF section to the output file. 00379 result = dwarf_get_relocation_info_count(dw_dbg, 00380 &relocation_section_count, 00381 &reloc_buffer_version, 00382 &dw_error); 00383 if (result != DW_DLV_OK) { 00384 fprintf(stderr, "ERROR Couldn't get relocation buffer count\n"); 00385 exit(-1); 00386 } 00387 if (reloc_buffer_version != 2 /* DWARF_DRD_BUFFER_VERSION */) { 00388 fprintf(stderr, 00389 "ERROR Relocation buffer format unrecognized " 00390 "(version %d)\n", reloc_buffer_version); 00391 exit(-1); 00392 } 00393 00394 for (i = 0; i < relocation_section_count; i++) { 00395 Dwarf_Relocation_Data reloc_buf; 00396 Dwarf_Unsigned entry_count; 00397 Dwarf_Signed link_scn; 00398 00399 result = dwarf_get_relocation_info(dw_dbg, &scndx, &link_scn, 00400 &entry_count, &reloc_buf, 00401 &dw_error); 00402 if (result != DW_DLV_OK) { 00403 fprintf(stderr, "ERROR dwarf_get_relocation_info failed\n"); 00404 exit(-1); 00405 } 00406 00407 current_scn = -1; 00408 00409 Dwarf_Signed j = find_indexed_section(current_scn + 1, link_scn); 00410 00411 BOOL is_debug_line = 00412 (strcmp(".debug_line", 00413 Em_Get_Section_Name(index_to_buffer_map[j].cursection)) == 0); 00414 00415 buffer = 00416 Em_Dwarf_Symbolic_Relocs_To_Elf(get_current_buffer, 00417 get_current_bufsize, 00418 advance_to_next_stream_buffer, 00419 link_scn, 00420 reloc_buf, entry_count, 00421 // Cheap hack to see if 00422 // this is a 64-bit compile: 00423 data_alignment_factor == -8, 00424 (is_debug_line ? 00425 identity_function : 00426 translate_dwarf_sym), 00427 &bufsize); 00428 cursection = Em_Dwarf_Find_Dwarf_Scn(scndx); 00429 if (cursection != NULL) { 00430 Em_Add_Bytes_To_Scn(cursection, buffer, bufsize, 1); 00431 } 00432 else { 00433 fprintf (stderr, "ERROR No such section index: %d\n", (int)scndx); 00434 exit(-1); 00435 } 00436 free((void *) buffer); 00437 } 00438 00439 for (i = 0; i < section_count; ++i) { 00440 Em_Add_Bytes_To_Scn (index_to_buffer_map[i].cursection, 00441 index_to_buffer_map[i].buffer, 00442 index_to_buffer_map[i].bufsize, 00443 1); 00444 } 00445 00446 free(index_to_buffer_map); 00447 00448 for (i = 0; i < num_dwarf_scns; i++) { 00449 Em_End_Section (dwarf_scn[i]); 00450 } 00451 } 00452 00453 extern "C" void 00454 Em_Dwarf_Write_Scns (void) 00455 { 00456 Em_Dwarf_Write_Scns(NULL); 00457 } 00458 00459 INT 00460 Em_Dwarf_Prepare_Output(void) 00461 { 00462 section_count = dwarf_transform_to_disk_form (dw_dbg, &dw_error); 00463 if (section_count == DW_DLV_NOCOUNT) { 00464 fprintf(stderr, "ERROR in dwarf_transform_to_disk_form\n"); 00465 exit(-1); 00466 } 00467 return (INT) section_count; 00468 } 00469 00470 void 00471 Em_Dwarf_End (void) 00472 { 00473 dwarf_producer_finish (dw_dbg, &dw_error); 00474 } 00475 00476 00477 void 00478 Em_Dwarf_Add_Line_Entry ( INT code_address, SRCPOS srcpos) 00479 { 00480 USRCPOS usrcpos; 00481 00482 USRCPOS_srcpos(usrcpos) = srcpos; 00483 00484 dwarf_add_line_entry (dw_dbg, 00485 file_table[USRCPOS_filenum(usrcpos)].dwarf_idx, 00486 code_address, 00487 USRCPOS_linenum(usrcpos), 00488 USRCPOS_column(usrcpos), 00489 USRCPOS_stmt_begin(usrcpos), 00490 USRCPOS_bb_begin(usrcpos), 00491 &dw_error); 00492 } 00493 00494 00495 #ifndef MONGOOSE_BE 00496 /* Given a file_index, return the filename and the path for the file. */ 00497 void 00498 Em_Dwarf_File_Index_To_Name (INT file_index, char **filename, char **path) 00499 { 00500 *filename = file_table[file_index].filename; 00501 *path = incl_table[file_table[file_index].incl_idx].path; 00502 } 00503 #endif /* MONGOOSE_BE */ 00504 00505 00506 /* the starting offset in the text region */ 00507 static INT Text_Start_Offset; 00508 static Dwarf_Unsigned Text_Start_Label; 00509 static Dwarf_Addr Offset_From_Text_Start_Label; 00510 00511 void 00512 Em_Dwarf_Start_Text_Lines (pSCNINFO scninfo, INT start_offset) 00513 { 00514 Text_Start_Offset = start_offset; 00515 dwarf_lne_set_address (dw_dbg, start_offset, 00516 Em_Create_Section_Symbol(scninfo), &dw_error); 00517 } 00518 00519 void 00520 Em_Dwarf_Start_Text_Region (pSCNINFO scninfo, INT start_offset) 00521 { 00522 Em_Dwarf_Start_Text_Lines (scninfo, start_offset); 00523 } 00524 00525 void 00526 Em_Dwarf_Start_Text_Region_Semi_Symbolic (pSCNINFO scninfo, 00527 INT start_offset, 00528 Dwarf_Unsigned first_label, 00529 Dwarf_Addr offset_from_first_label) 00530 { 00531 Text_Start_Offset = start_offset; 00532 Text_Start_Label = first_label; 00533 Offset_From_Text_Start_Label = offset_from_first_label; 00534 } 00535 00536 void 00537 Em_Dwarf_End_Text_Lines (pSCNINFO scninfo, INT end_offset) 00538 { 00539 dwarf_lne_end_sequence (dw_dbg, end_offset, &dw_error); 00540 } 00541 00542 void 00543 Em_Dwarf_End_Text_Arange (pSCNINFO scninfo, INT end_offset) 00544 { 00545 INT region_size = end_offset - Text_Start_Offset; 00546 00547 dwarf_add_arange (dw_dbg, Text_Start_Offset, region_size, 00548 Em_Create_Section_Symbol(scninfo), &dw_error); 00549 } 00550 00551 void 00552 Em_Dwarf_End_Text_Arange_Symbolic(Dwarf_Unsigned last_label, 00553 Dwarf_Addr offset_from_last_label) 00554 { 00555 dwarf_add_arange_b (dw_dbg, 00556 Offset_From_Text_Start_Label, 00557 0 /* dummy length */, 00558 Text_Start_Label, 00559 last_label, 00560 offset_from_last_label, 00561 &dw_error); 00562 } 00563 00564 void 00565 Em_Dwarf_End_Text_Region (pSCNINFO scninfo, INT end_offset) 00566 { 00567 Em_Dwarf_End_Text_Arange (scninfo, end_offset); 00568 Em_Dwarf_End_Text_Lines (scninfo, end_offset); 00569 } 00570 00571 void 00572 Em_Dwarf_End_Text_Region_Semi_Symbolic(pSCNINFO scninfo, 00573 INT end_offset, 00574 Dwarf_Unsigned last_label, 00575 Dwarf_Addr offset_from_last_label) 00576 { 00577 Em_Dwarf_End_Text_Arange_Symbolic(last_label, 00578 offset_from_last_label); 00579 Em_Dwarf_End_Text_Lines(scninfo, end_offset); 00580 } 00581 00582 void Em_Dwarf_Process_PU (Dwarf_Unsigned begin_label, 00583 Dwarf_Unsigned end_label, 00584 INT32 begin_offset, 00585 INT32 end_offset, 00586 Dwarf_P_Die PU_die, 00587 Dwarf_P_Fde fde, 00588 Elf64_Word eh_symindex, 00589 INT eh_offset) 00590 { 00591 /* setup the low_pc and the high_pc attributes. */ 00592 dwarf_add_AT_targ_address_b (dw_dbg, PU_die, DW_AT_low_pc, 00593 begin_offset, 00594 (Dwarf_Unsigned) begin_label, 00595 &dw_error); 00596 dwarf_add_AT_targ_address_b (dw_dbg, PU_die, DW_AT_high_pc, 00597 end_offset, (Dwarf_Unsigned) end_label, 00598 &dw_error); 00599 00600 if (fde == NULL) 00601 return; 00602 /* emit the debug_frame information for this procedure. */ 00603 if (eh_offset == DW_DLX_NO_EH_OFFSET) /* no exception handler */ 00604 dwarf_add_frame_fde_b (dw_dbg, fde, PU_die, cie_index, 00605 begin_offset, 00606 0 /* dummy code length */, 00607 (Dwarf_Unsigned) begin_label, 00608 (Dwarf_Unsigned) end_label, 00609 end_offset, 00610 &dw_error); 00611 else 00612 dwarf_add_frame_info_b (dw_dbg, fde, PU_die, cie_index, 00613 begin_offset, 00614 0 /* dummy code length */, 00615 (Dwarf_Unsigned) begin_label, 00616 (Dwarf_Unsigned) end_label, 00617 end_offset, 00618 eh_offset, eh_symindex, &dw_error); 00619 }