Exemplo n.º 1
0
/*
    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,
							&reg,
							&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,
						    &reg,
						    &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,
						   &reg,
						   &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;
}
Exemplo n.º 2
0
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, &register_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, &register_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, &register_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, &reg_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++;
	}
}