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 #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
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
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
00124
00125
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
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
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
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)
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
00378
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 ) {
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
00422
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
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
00504
00505
00506
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 ,
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
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
00603 if (eh_offset == DW_DLX_NO_EH_OFFSET)
00604 dwarf_add_frame_fde_b (dw_dbg, fde, PU_die, cie_index,
00605 begin_offset,
00606 0 ,
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 ,
00615 (Dwarf_Unsigned) begin_label,
00616 (Dwarf_Unsigned) end_label,
00617 end_offset,
00618 eh_offset, eh_symindex, &dw_error);
00619 }