/* Gather the fde print logic here so the control logic determining what FDE to print is clearer. */ int print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde, Dwarf_Unsigned fde_index, Dwarf_Cie * cie_data, Dwarf_Signed cie_element_count, Dwarf_Half address_size, int is_eh, struct dwconf_s *config_data) { Dwarf_Addr j = 0; Dwarf_Addr low_pc = 0; Dwarf_Unsigned func_length = 0; Dwarf_Ptr fde_bytes = NULL; Dwarf_Unsigned fde_bytes_length = 0; Dwarf_Off cie_offset = 0; Dwarf_Signed cie_index = 0; Dwarf_Off fde_offset = 0; Dwarf_Signed eh_table_offset = 0; int fres = 0; int offres = 0; string temps = 0; Dwarf_Error err = 0; int printed_intro_addr = 0; fres = dwarf_get_fde_range(fde, &low_pc, &func_length, &fde_bytes, &fde_bytes_length, &cie_offset, &cie_index, &fde_offset, &err); if (fres == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_fde_range", fres, err); } if (fres == DW_DLV_NO_ENTRY) { return DW_DLV_NO_ENTRY; } if (cu_name_flag && fde_offset_for_cu_low != DW_DLV_BADOFFSET && (fde_offset < fde_offset_for_cu_low || fde_offset > fde_offset_for_cu_high)) { return DW_DLV_NO_ENTRY; } /* eh_table_offset is IRIX ONLY. */ fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err); if (fres == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_fde_exception_info", fres, err); } temps = get_fde_proc_name(dbg, low_pc); printf ("<%3lld><%#llx:%#llx><%s><fde offset 0x%llx length: 0x%llx>", cie_index, low_pc, (low_pc + func_length), temps ? temps : "", fde_offset, fde_bytes_length); if (!is_eh) { /* IRIX uses eh_table_offset. */ if (eh_table_offset == DW_DLX_NO_EH_OFFSET) { printf("<eh offset %s>\n", "none"); } else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) { printf("<eh offset %s>\n", "unknown"); } else { printf("<eh offset 0x%llx>\n", eh_table_offset); } } else { int ares = 0; Dwarf_Small *data = 0; Dwarf_Unsigned len = 0; ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err); if (ares == DW_DLV_NO_ENTRY) { /* do nothing. */ } else if (ares == DW_DLV_OK) { int k2; printf("<eh aug data len 0x%llx", (long long) len); for (k2 = 0; k2 < len; ++k2) { if (k2 == 0) { printf(" bytes 0x"); } printf("%02x ", (unsigned char) data[k2]); } printf(">"); } /* else DW_DLV_ERROR, do nothing */ printf("\n"); } /* call dwarf_get_fde_info_for_reg() to get whole matrix */ for (j = low_pc; j < low_pc + func_length; j++) { Dwarf_Half k; if (config_data->cf_interface_number == 3) { Dwarf_Signed reg = 0; Dwarf_Signed offset_relevant = 0; Dwarf_Small value_type = 0; Dwarf_Signed offset_or_block_len = 0; Dwarf_Signed offset = 0; Dwarf_Ptr block_ptr = 0; Dwarf_Addr row_pc = 0; int fires = dwarf_get_fde_info_for_cfa_reg3(fde, j, &value_type, &offset_relevant, ®, &offset_or_block_len, &block_ptr, &row_pc, &err); offset = offset_or_block_len; if (fires == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_fde_info_for_reg", fires, err); } if (fires == DW_DLV_NO_ENTRY) { continue; } if (row_pc != j) { /* duplicate row */ continue; } if (!printed_intro_addr) { printf(" %08llx:\t", j); printed_intro_addr = 1; } print_one_frame_reg_col(dbg, config_data->cf_cfa_reg, value_type, reg, config_data, offset_relevant, offset, block_ptr); } for (k = 0; k < config_data->cf_table_entry_count; k++) { Dwarf_Signed reg = 0; Dwarf_Signed offset_relevant = 0; int fires = 0; Dwarf_Small value_type = 0; Dwarf_Ptr block_ptr = 0; Dwarf_Signed offset_or_block_len = 0; Dwarf_Signed offset = 0; Dwarf_Addr row_pc = 0; if (config_data->cf_interface_number == 3) { fires = dwarf_get_fde_info_for_reg3(fde, k, j, &value_type, &offset_relevant, ®, &offset_or_block_len, &block_ptr, &row_pc, &err); offset = offset_or_block_len; } else { /* ASSERT: config_data->cf_interface_number == 2 */ value_type = DW_EXPR_OFFSET; fires = dwarf_get_fde_info_for_reg(fde, k, j, &offset_relevant, ®, &offset, &row_pc, &err); } if (fires == DW_DLV_ERROR) { printf("\n"); print_error(dbg, "dwarf_get_fde_info_for_reg", fires, err); } if (fires == DW_DLV_NO_ENTRY) { continue; } if (row_pc != j) { /* duplicate row */ break; } if (!printed_intro_addr) { printf(" %08llx:\t", j); printed_intro_addr = 1; } print_one_frame_reg_col(dbg,k, value_type, reg, config_data, offset_relevant, offset, block_ptr); } if (printed_intro_addr) { printf("\n"); printed_intro_addr = 0; } } if (verbose > 1) { Dwarf_Off fde_off; Dwarf_Off cie_off; /* get the fde instructions and print them in raw form, just like cie instructions */ Dwarf_Ptr instrs; Dwarf_Unsigned ilen; int res; res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err); offres = dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off, &err); if (offres == DW_DLV_OK) { printf("\tfde sec. offset %llu 0x%llx" " cie offset for fde: %llu 0x%llx\n", (unsigned long long) fde_off, (unsigned long long) fde_off, (unsigned long long) cie_off, (unsigned long long) cie_off); } if (res == DW_DLV_OK) { int cires = 0; Dwarf_Unsigned cie_length = 0; Dwarf_Small version = 0; string augmenter; Dwarf_Unsigned code_alignment_factor = 0; Dwarf_Signed data_alignment_factor = 0; Dwarf_Half return_address_register_rule = 0; Dwarf_Ptr initial_instructions = 0; Dwarf_Unsigned initial_instructions_length = 0; if (cie_index >= cie_element_count) { printf("Bad cie index %lld with fde index %lld! " "(table entry max %lld)\n", (long long) cie_index, (long long) fde_index, (long long) cie_element_count); exit(1); } cires = dwarf_get_cie_info(cie_data[cie_index], &cie_length, &version, &augmenter, &code_alignment_factor, &data_alignment_factor, &return_address_register_rule, &initial_instructions, &initial_instructions_length, &err); if (cires == DW_DLV_ERROR) { printf ("Bad cie index %lld with fde index %lld!\n", (long long) cie_index, (long long) fde_index); print_error(dbg, "dwarf_get_cie_info", cires, err); } if (cires == DW_DLV_NO_ENTRY) { ; /* ? */ } else { print_frame_inst_bytes(dbg, instrs, (Dwarf_Signed) ilen, data_alignment_factor, (int) code_alignment_factor, address_size, config_data); } } else if (res == DW_DLV_NO_ENTRY) { printf ("Impossible: no instr bytes for fde index %d?\n", (int) fde_index); } else { /* DW_DLV_ERROR */ printf ("Error: on gettinginstr bytes for fde index %d?\n", (int) fde_index); print_error(dbg, "dwarf_get_fde_instr_bytes", res, err); } } return DW_DLV_OK; }
static void _frame3_test(Dwarf_Debug dbg, Dwarf_Fde fde, Dwarf_Addr pc, Dwarf_Unsigned func_len, Dwarf_Unsigned caf) { Dwarf_Signed offset_relevant, register_num, offset_or_block_len; Dwarf_Addr pc_end, row_pc; Dwarf_Ptr block_ptr; Dwarf_Regtable3 reg_table3; Dwarf_Small value_type; Dwarf_Error de; int i, cnt; /* Initialise regster table (DWARF3). */ reg_table3.rt3_reg_table_size = DW_REG_TABLE_SIZE; reg_table3.rt3_rules = calloc(reg_table3.rt3_reg_table_size, sizeof(Dwarf_Regtable_Entry3)); if (reg_table3.rt3_rules == NULL) { tet_infoline("calloc failed when initialising reg_table3"); result = TET_FAIL; return; } /* Sanity check for invalid table_column. */ if (dwarf_get_fde_info_for_reg3(fde, 9999, 0, &value_type, &offset_relevant, ®ister_num, &offset_or_block_len, &block_ptr, &row_pc, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_get_fde_info_for_reg3 didn't return" " DW_DLV_ERROR when called with invalid table_column" " value"); result = TET_FAIL; return; } cnt = 0; pc_end = pc + func_len; while (pc < pc_end && cnt < 16) { tet_printf("query CFA(3) register pc %#jx\n", (uintmax_t) pc); if (dwarf_get_fde_info_for_cfa_reg3(fde, pc, &value_type, &offset_relevant, ®ister_num, &offset_or_block_len, &block_ptr, &row_pc, &de) != DW_DLV_OK) { tet_printf("dwarf_get_fde_info_for_reg3(cfa) failed: %s", dwarf_errmsg(de)); result = TET_FAIL; return; } TS_CHECK_INT(value_type); TS_CHECK_INT(offset_relevant); TS_CHECK_INT(offset_or_block_len); TS_CHECK_INT(register_num); TS_CHECK_UINT(row_pc); if (value_type == DW_EXPR_EXPRESSION || value_type == DW_EXPR_VAL_EXPRESSION) TS_CHECK_BLOCK(block_ptr, offset_or_block_len); for (i = 1; i < _MAX_REG_NUM; i++) { tet_printf("query register(3) %d\n", i); if (dwarf_get_fde_info_for_reg3(fde, i, pc, &value_type, &offset_relevant, ®ister_num, &offset_or_block_len, &block_ptr, &row_pc, &de) != DW_DLV_OK) { tet_printf("dwarf_get_fde_info_for_reg3(%d)" " failed: %s", i, dwarf_errmsg(de)); result = TET_FAIL; goto next; } TS_CHECK_INT(value_type); TS_CHECK_INT(offset_relevant); TS_CHECK_INT(offset_or_block_len); TS_CHECK_INT(register_num); TS_CHECK_UINT(row_pc); if (value_type == DW_EXPR_EXPRESSION || value_type == DW_EXPR_VAL_EXPRESSION) TS_CHECK_BLOCK(block_ptr, offset_or_block_len); } tet_infoline("query all register(3)"); if (dwarf_get_fde_info_for_all_regs3(fde, pc, ®_table3, &row_pc, &de) != DW_DLV_OK) { tet_printf("dwarf_get_fde_info_for_all_regs failed: %s", dwarf_errmsg(de)); result = TET_FAIL; goto next; } TS_CHECK_UINT(row_pc); #define CFA3 reg_table3.rt3_cfa_rule #define RT3 reg_table3.rt3_rules TS_CHECK_UINT(CFA3.dw_offset_relevant); TS_CHECK_UINT(CFA3.dw_value_type); TS_CHECK_UINT(CFA3.dw_regnum); TS_CHECK_UINT(CFA3.dw_offset_or_block_len); if (CFA3.dw_value_type == DW_EXPR_EXPRESSION || CFA3.dw_value_type == DW_EXPR_VAL_EXPRESSION) TS_CHECK_BLOCK(CFA3.dw_block_ptr, CFA3.dw_offset_or_block_len); for (i = 0; i < _MAX_REG_NUM; i++) { tet_printf("check reg_table3[%d]\n", i); TS_CHECK_UINT(RT3[i].dw_offset_relevant); TS_CHECK_UINT(RT3[i].dw_value_type); TS_CHECK_UINT(RT3[i].dw_regnum); TS_CHECK_UINT(RT3[i].dw_offset_or_block_len); if (RT3[i].dw_value_type == DW_EXPR_EXPRESSION || RT3[i].dw_value_type == DW_EXPR_VAL_EXPRESSION) TS_CHECK_BLOCK(RT3[i].dw_block_ptr, RT3[i].dw_offset_or_block_len); } #undef CFA3 #undef RT3 next: pc += caf; cnt++; } }