extern void print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die) { Dwarf_Unsigned lineversion = 0; Dwarf_Signed linecount = 0; Dwarf_Line *linebuf = NULL; Dwarf_Signed linecount_actuals = 0; Dwarf_Line *linebuf_actuals = NULL; Dwarf_Small table_count = 0; int lres = 0; int line_errs = 0; Dwarf_Line_Context line_context = 0; const char *sec_name = 0; current_section_id = DEBUG_LINE; /* line_flag is TRUE */ lres = dwarf_get_line_section_name_from_die(cu_die, &sec_name,&err); if (lres != DW_DLV_OK || !sec_name || !strlen(sec_name)) { sec_name = ".debug_line"; } if (do_print_dwarf) { printf("\n%s: line number info for a single cu\n", sec_name); } else { /* We are checking, not printing. */ Dwarf_Half tag = 0; int tres = dwarf_tag(cu_die, &tag, &err); if (tres != DW_DLV_OK) { /* Something broken here. */ print_error(dbg,"Unable to see CU DIE tag " "though we could see it earlier. Something broken.", tres,err); return; } else if (tag == DW_TAG_type_unit) { /* Not checking since type units missing address or range in CU header. */ return; } } if (verbose > 1) { int errcount = 0; print_source_intro(cu_die); print_one_die(dbg, cu_die, /* print_information= */ 1, /* indent level */0, /* srcfiles= */ 0, /* cnt= */ 0, /* ignore_die_stack= */TRUE); DWARF_CHECK_COUNT(lines_result,1); lres = dwarf_print_lines(cu_die, &err,&errcount); if (errcount > 0) { DWARF_ERROR_COUNT(lines_result,errcount); DWARF_CHECK_COUNT(lines_result,(errcount-1)); } if (lres == DW_DLV_ERROR) { print_error(dbg, "dwarf_srclines details", lres, err); } return; } if (check_lines && checking_this_compiler()) { DWARF_CHECK_COUNT(lines_result,1); dwarf_check_lineheader(cu_die,&line_errs); if (line_errs > 0) { DWARF_CHECK_ERROR_PRINT_CU(); DWARF_ERROR_COUNT(lines_result,line_errs); DWARF_CHECK_COUNT(lines_result,(line_errs-1)); } } /* The following is complicated by a desire to test various line table interface functions. Hence we test line_flag_selection. Normal code should pick an interface (for most the best choice is what we here call line_flag_selection == std) and use just that interface set. Sorry about the length of the code that results from having so many interfaces. */ if (line_flag_selection == std) { lres = dwarf_srclines_b(cu_die,&lineversion, &table_count,&line_context, &err); if(lres == DW_DLV_OK) { lres = dwarf_srclines_from_linecontext(line_context, &linebuf, &linecount,&err); } } else if (line_flag_selection == orig) { /* DWARF2,3,4, ok for 5. */ /* Useless for experimental line tables */ lres = dwarf_srclines(cu_die, &linebuf, &linecount, &err); if(lres == DW_DLV_OK && linecount ){ table_count++; } } else if (line_flag_selection == orig2l) { lres = dwarf_srclines_two_level(cu_die, &lineversion, &linebuf, &linecount, &linebuf_actuals, &linecount_actuals, &err); if(lres == DW_DLV_OK && linecount){ table_count++; } if(lres == DW_DLV_OK && linecount_actuals){ table_count++; } } else if (line_flag_selection == s2l) { lres = dwarf_srclines_b(cu_die,&lineversion, &table_count,&line_context, &err); if(lres == DW_DLV_OK) { lres = dwarf_srclines_two_level_from_linecontext(line_context, &linebuf, &linecount, &linebuf_actuals, &linecount_actuals, &err); } } if (lres == DW_DLV_ERROR) { /* Do not terminate processing */ if (check_decl_file) { DWARF_CHECK_COUNT(decl_file_result,1); DWARF_CHECK_ERROR2(decl_file_result,"dwarf_srclines", dwarf_errmsg(err)); record_dwarf_error = FALSE; /* Clear error condition */ } else { print_error(dbg, "dwarf_srclines", lres, err); } } else if (lres == DW_DLV_NO_ENTRY) { /* no line information is included */ } else if (table_count > 0) { /* DW_DLV_OK */ if(line_context && verbose) { print_line_context_record(dbg,line_context); } if (do_print_dwarf) { print_source_intro(cu_die); if (verbose) { print_one_die(dbg, cu_die, /* print_information= */ TRUE, /* indent_level= */ 0, /* srcfiles= */ 0, /* cnt= */ 0, /* ignore_die_stack= */TRUE); } } if(line_flag_selection == std || line_flag_selection == s2l) { if (table_count == 0 || table_count == 1) { /* ASSERT: is_single_table == true */ Dwarf_Bool is_logicals = FALSE; Dwarf_Bool is_actuals = FALSE; process_line_table(dbg,sec_name, linebuf, linecount, is_logicals,is_actuals); } else { Dwarf_Bool is_logicals = TRUE; Dwarf_Bool is_actuals = FALSE; process_line_table(dbg,sec_name, linebuf, linecount, is_logicals, is_actuals); process_line_table(dbg,sec_name, linebuf_actuals, linecount_actuals, !is_logicals, !is_actuals); } dwarf_srclines_dealloc_b(line_context); } else if (line_flag_selection == orig) { Dwarf_Bool is_logicals = FALSE; Dwarf_Bool is_actuals = FALSE; process_line_table(dbg,sec_name, linebuf, linecount, is_logicals, is_actuals); dwarf_srclines_dealloc(dbg,linebuf,linecount); } else if (line_flag_selection == orig2l) { if (table_count == 1 || table_count == 0) { Dwarf_Bool is_logicals = FALSE; Dwarf_Bool is_actuals = FALSE; process_line_table(dbg,sec_name, linebuf, linecount, is_logicals, is_actuals); } else { Dwarf_Bool is_logicals = TRUE; Dwarf_Bool is_actuals = FALSE; process_line_table(dbg,sec_name, linebuf, linecount, is_logicals, is_actuals); process_line_table(dbg,sec_name, linebuf_actuals, linecount_actuals, !is_logicals, !is_actuals); } dwarf_srclines_dealloc(dbg,linebuf,linecount); } /* end, table_count > 0 */ } else { /* DW_DLV_OK */ /* table_count == 0. no lines in table. Just a line table header. */ if (do_print_dwarf) { int ores = 0; Dwarf_Unsigned off = 0; print_source_intro(cu_die); if (verbose) { print_one_die(dbg, cu_die, /* print_information= */ TRUE, /* indent_level= */ 0, /* srcfiles= */ 0, /* cnt= */ 0, /* ignore_die_stack= */TRUE); } if(line_context) { if (verbose > 2) { print_line_context_record(dbg,line_context); } ores = dwarf_srclines_table_offset(line_context, &off,&err); if (ores != DW_DLV_OK) { print_error(dbg,"dwarf_srclines_table_offset fail",ores,err); } else { printf(" Line table is present (offset 0x%" DW_PR_XZEROS DW_PR_DUx ") but no lines present\n", off); } } else { printf(" Line table is present but no lines present\n"); } } if(line_flag_selection == std || line_flag_selection == s2l) { dwarf_srclines_dealloc_b(line_context); } else { /* Original allocation. */ dwarf_srclines_dealloc(dbg,linebuf,linecount); } /* end, linecounttotal == 0 */ } }
/* return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR If err_count_out is non-NULL, this is a special 'check' call. */ static int _dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error, int * err_count_out, int only_line_header) { /* This pointer is used to scan the portion of the .debug_line section for the current cu. */ Dwarf_Small *line_ptr = 0; Dwarf_Small *orig_line_ptr = 0; /* Pointer to a DW_AT_stmt_list attribute in case it exists in the die. */ Dwarf_Attribute stmt_list_attr = 0; /* Pointer to DW_AT_comp_dir attribute in die. */ Dwarf_Attribute comp_dir_attr = 0; /* Pointer to name of compilation directory. */ Dwarf_Small *comp_dir = NULL; /* Offset into .debug_line specified by a DW_AT_stmt_list attribute. */ Dwarf_Unsigned line_offset = 0; Dwarf_Sword i=0; Dwarf_Word u=0; /* These variables are used to decode leb128 numbers. Leb128_num holds the decoded number, and leb128_length is its length in bytes. */ Dwarf_Half attrform = 0; /* In case there are wierd bytes 'after' the line table prologue this lets us print something. This is a gcc compiler bug and we expect the bytes count to be 12. */ Dwarf_Small* bogus_bytes_ptr = 0; Dwarf_Unsigned bogus_bytes_count = 0; Dwarf_Half address_size = 0; Dwarf_Unsigned fission_offset = 0; /* The Dwarf_Debug this die belongs to. */ Dwarf_Debug dbg=0; Dwarf_CU_Context cu_context = 0; Dwarf_Line_Context line_context = 0; int resattr = DW_DLV_ERROR; int lres = DW_DLV_ERROR; int res = DW_DLV_ERROR; Dwarf_Small *line_ptr_actuals = 0; Dwarf_Small *line_ptr_end = 0; Dwarf_Small *section_start = 0; /* ***** BEGIN CODE ***** */ if (error != NULL) { *error = NULL; } CHECK_DIE(die, DW_DLV_ERROR); cu_context = die->di_cu_context; dbg = cu_context->cc_dbg; res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); if (res != DW_DLV_OK) { return res; } if (!dbg->de_debug_line.dss_size) { return (DW_DLV_NO_ENTRY); } address_size = _dwarf_get_address_size(dbg, die); resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); if (resattr != DW_DLV_OK) { return resattr; } /* The list of relevant FORMs is small. DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset */ lres = dwarf_whatform(stmt_list_attr,&attrform,error); if (lres != DW_DLV_OK) { return lres; } if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && attrform != DW_FORM_sec_offset ) { _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); return (DW_DLV_ERROR); } lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); if (lres != DW_DLV_OK) { return lres; } if (line_offset >= dbg->de_debug_line.dss_size) { _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); return (DW_DLV_ERROR); } section_start = dbg->de_debug_line.dss_data; { Dwarf_Unsigned fission_size = 0; int resfis = _dwarf_get_fission_addition_die(die, DW_SECT_LINE, &fission_offset,&fission_size,error); if(resfis != DW_DLV_OK) { return resfis; } } orig_line_ptr = section_start + line_offset + fission_offset; line_ptr = orig_line_ptr; dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); /* If die has DW_AT_comp_dir attribute, get the string that names the compilation directory. */ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); if (resattr == DW_DLV_ERROR) { return resattr; } if (resattr == DW_DLV_OK) { int cres = DW_DLV_ERROR; char *cdir = 0; cres = dwarf_formstring(comp_dir_attr, &cdir, error); if (cres == DW_DLV_ERROR) { return cres; } else if (cres == DW_DLV_OK) { comp_dir = (Dwarf_Small *) cdir; } } if (resattr == DW_DLV_OK) { dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); } line_context = (Dwarf_Line_Context) _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1); if (line_context == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } { Dwarf_Small *newlinep = 0; int dres = _dwarf_read_line_table_header(dbg, cu_context, section_start, line_ptr, dbg->de_debug_line.dss_size, &newlinep, line_context, &bogus_bytes_ptr, &bogus_bytes_count, error, err_count_out); if (dres == DW_DLV_ERROR) { dwarf_srclines_dealloc_b(line_context); return dres; } if (dres == DW_DLV_NO_ENTRY) { dwarf_srclines_dealloc_b(line_context); return dres; } line_ptr_end = line_context->lc_line_ptr_end; line_ptr = newlinep; if (line_context->lc_actuals_table_offset > 0) { line_ptr_actuals = line_context->lc_line_prologue_start + line_context->lc_actuals_table_offset; } } line_context->lc_compilation_directory = comp_dir; if (only_line_header) { /* Just checking for header errors, nothing more here.*/ dwarf_srclines_dealloc_b(line_context); return DW_DLV_OK; } dwarf_printf(dbg, "total line info length %ld bytes," " line offset 0x%" DW_PR_XZEROS DW_PR_DUx " %" DW_PR_DUu "\n", (long) line_context->lc_total_length, line_context->lc_section_offset, line_context->lc_section_offset); if (line_context->lc_version_number <= DW_LINE_VERSION5) { dwarf_printf(dbg, "line table version %d\n",(int) line_context->lc_version_number); } else { dwarf_printf(dbg, "line table version 0x%x\n",(int) line_context->lc_version_number); } dwarf_printf(dbg, "line table length field length %d prologue length %d\n", (int)line_context->lc_length_field_length, (int)line_context->lc_prologue_length); dwarf_printf(dbg, "compilation_directory %s\n", comp_dir ? ((char *) comp_dir) : ""); dwarf_printf(dbg, " min instruction length %d\n", (int) line_context->lc_minimum_instruction_length); if (line_context->lc_version_number == EXPERIMENTAL_LINE_TABLES_VERSION) { dwarf_printf(dbg, " actuals table offset " "0x%" DW_PR_XZEROS DW_PR_DUx " logicals table offset " "0x%" DW_PR_XZEROS DW_PR_DUx "\n", line_context->lc_actuals_table_offset, line_context->lc_logicals_table_offset); } if (line_context->lc_version_number == DW_LINE_VERSION5) { dwarf_printf(dbg, " segment selector size %d\n", (int) line_context->lc_segment_selector_size); dwarf_printf(dbg, " address size %d\n", (int) line_context->lc_address_size); } dwarf_printf(dbg, " default is stmt %d\n",(int)line_context->lc_default_is_stmt); dwarf_printf(dbg, " line base %d\n",(int)line_context->lc_line_base); dwarf_printf(dbg, " line_range %d\n",(int)line_context->lc_line_range); dwarf_printf(dbg, " opcode base %d\n",(int)line_context->lc_opcode_base); dwarf_printf(dbg, " standard opcode count %d\n",(int)line_context->lc_std_op_count); for (i = 1; i < line_context->lc_opcode_base; i++) { dwarf_printf(dbg, " opcode[%2d] length %d\n", (int) i, (int) line_context->lc_opcode_length_table[i - 1]); } dwarf_printf(dbg, " include directories count %d\n", (int) line_context->lc_include_directories_count); for (u = 0; u < line_context->lc_include_directories_count; ++u) { dwarf_printf(dbg, " include dir[%u] %s\n", (int) u, line_context->lc_include_directories[u]); } dwarf_printf(dbg, " files count %d\n", (int) line_context->lc_file_entry_count); if (line_context->lc_file_entry_count) { Dwarf_File_Entry fe = line_context->lc_file_entries; Dwarf_File_Entry fe2 = fe; unsigned fiu = 0; for (fiu = 0 ; fe2 ; fe2 = fe->fi_next,++fiu ) { Dwarf_Unsigned tlm2 = 0; Dwarf_Unsigned di = 0; Dwarf_Unsigned fl = 0; fe = fe2; tlm2 = fe->fi_time_last_mod; di = fe->fi_dir_index; fl = fe->fi_file_length; dwarf_printf(dbg, " file[%u] %s (file-number: %u) \n", (unsigned) fiu, (char *) fe->fi_file_name, (unsigned)(fiu+1)); dwarf_printf(dbg, " dir index %d\n", (int) di); { time_t tt = (time_t) tlm2; /* ctime supplies newline */ dwarf_printf(dbg, " last time 0x%x %s", (unsigned) tlm2, ctime(&tt)); } dwarf_printf(dbg, " file length %ld 0x%lx\n", (long) fl, (unsigned long) fl); } } if (line_context->lc_version_number == EXPERIMENTAL_LINE_TABLES_VERSION) { /* Print the subprograms list. */ Dwarf_Unsigned count = line_context->lc_subprogs_count; Dwarf_Unsigned exu = 0; Dwarf_Subprog_Entry sub = line_context->lc_subprogs; dwarf_printf(dbg," subprograms count" " %" DW_PR_DUu "\n",count); if (count > 0) { dwarf_printf(dbg," indx file line name\n"); } for (exu = 0 ; exu < count ; exu++,sub++) { dwarf_printf(dbg," [%2" DW_PR_DUu "] %4" DW_PR_DUu " %4" DW_PR_DUu " %s\n", exu+1, sub->ds_decl_file, sub->ds_decl_line, sub->ds_subprog_name); } } { Dwarf_Unsigned offset = 0; if (bogus_bytes_count > 0) { Dwarf_Unsigned wcount = bogus_bytes_count; Dwarf_Unsigned boffset = bogus_bytes_ptr - section_start; dwarf_printf(dbg, "*** DWARF CHECK: the line table prologue header_length " " is %" DW_PR_DUu " too high, we pretend it is smaller." "Section offset: 0x%" DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ") ***\n", wcount, boffset,boffset); *err_count_out += 1; } offset = line_ptr - section_start; dwarf_printf(dbg, " statement prog offset in section: 0x%" DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ")\n", offset, offset); } { Dwarf_Bool doaddrs = false; Dwarf_Bool dolines = true; _dwarf_print_line_context_record(dbg,line_context); if (!line_ptr_actuals) { /* Normal single level line table. */ Dwarf_Bool is_single_table = true; Dwarf_Bool is_actuals_table = false; print_line_header(dbg, is_single_table, is_actuals_table); res = read_line_table_program(dbg, line_ptr, line_ptr_end, orig_line_ptr, section_start, line_context, address_size, doaddrs, dolines, is_single_table, is_actuals_table, error, err_count_out); if (res != DW_DLV_OK) { dwarf_srclines_dealloc_b(line_context); return res; } } else { Dwarf_Bool is_single_table = false; Dwarf_Bool is_actuals_table = false; if (line_context->lc_version_number != EXPERIMENTAL_LINE_TABLES_VERSION) { dwarf_srclines_dealloc_b(line_context); _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); return (DW_DLV_ERROR); } /* Read Logicals */ print_line_header(dbg, is_single_table, is_actuals_table); res = read_line_table_program(dbg, line_ptr, line_ptr_actuals, orig_line_ptr, section_start, line_context, address_size, doaddrs, dolines, is_single_table, is_actuals_table, error,err_count_out); if (res != DW_DLV_OK) { dwarf_srclines_dealloc_b(line_context); return res; } if (line_context->lc_actuals_table_offset > 0) { is_actuals_table = true; /* Read Actuals */ print_line_header(dbg, is_single_table, is_actuals_table); res = read_line_table_program(dbg, line_ptr_actuals, line_ptr_end, orig_line_ptr, section_start, line_context, address_size, doaddrs, dolines, is_single_table, is_actuals_table, error, err_count_out); if (res != DW_DLV_OK) { dwarf_srclines_dealloc_b(line_context); return res; } } } } dwarf_srclines_dealloc_b(line_context); return DW_DLV_OK; }