/*
    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;
}
Example #2
0
static void
_frame2_test(Dwarf_Debug dbg, Dwarf_Fde fde, Dwarf_Addr pc,
    Dwarf_Unsigned func_len, Dwarf_Unsigned caf)
{
	Dwarf_Signed offset_relevant, register_num, offset;
	Dwarf_Addr pc_end, row_pc;
	Dwarf_Regtable reg_table;
	Dwarf_Error de;
	int i, cnt;

	(void) dwarf_set_frame_cfa_value(dbg, DW_FRAME_CFA_COL);

	/* Sanity check for invalid table_column. */
	if (dwarf_get_fde_info_for_reg(fde, 9999, 0, &offset_relevant,
	    &register_num, &offset, &row_pc, &de) != DW_DLV_ERROR) {
		tet_infoline("dwarf_get_fde_info_for_reg 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 register pc %#jx\n", (uintmax_t) pc);
		/*
		 * XXX If application want to use DW_FRAME_CFA_COL for CFA,
		 * it should call dwarf_set_frame_cfa_value() to set that
		 * explicitly. So here DW_FRAME_CFA_COL might not be refering
		 * to the CFA at all, depends on whether CFA(0) is set by
		 * dwarf_set_frame_cfa_value.
		 */
		if (dwarf_get_fde_info_for_reg(fde, DW_FRAME_CFA_COL,
		    pc, &offset_relevant, &register_num, &offset,
		    &row_pc, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_fde_info_for_reg(cfa) failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
			return;
		}
		TS_CHECK_INT(offset_relevant);
		TS_CHECK_INT(offset);
		TS_CHECK_INT(register_num);
		TS_CHECK_UINT(row_pc);
		for (i = 1; i < _MAX_REG_NUM; i++) {
			tet_printf("query register %d\n", i);
			if (dwarf_get_fde_info_for_reg(fde, i, pc,
			    &offset_relevant, &register_num, &offset,
			    &row_pc, &de) != DW_DLV_OK) {
				tet_printf("dwarf_get_fde_info_for_reg(%d)"
				    " failed: %s", i, dwarf_errmsg(de));
				result = TET_FAIL;
				goto next;
			}
			TS_CHECK_INT(offset_relevant);
			TS_CHECK_INT(offset);
			TS_CHECK_INT(register_num);
			TS_CHECK_UINT(row_pc);
		}
		tet_infoline("query all register");
		if (dwarf_get_fde_info_for_all_regs(fde, pc, &reg_table,
		    &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);
		for (i = 0; i < _MAX_REG_NUM; i++) {
			tet_printf("check reg_table[%d]\n", i);
			TS_CHECK_UINT(reg_table.rules[i].dw_offset_relevant);
			TS_CHECK_UINT(reg_table.rules[i].dw_regnum);
			TS_CHECK_UINT(reg_table.rules[i].dw_offset);
		}
		
	next:
		pc += caf;
		cnt++;
	}
}