Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
em_dwarf.cxx
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines