예제 #1
0
static void
_dwarf_cie_fde_test(Dwarf_Debug dbg, int eh, void (*_frame_test)(Dwarf_Debug,
    Dwarf_Fde, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Unsigned))
{
	Dwarf_Cie *cielist, cie;
	Dwarf_Fde *fdelist, fde;
	Dwarf_Frame_Op *oplist;
	Dwarf_Signed ciecnt, fdecnt;
	Dwarf_Addr low_pc, high_pc;
	Dwarf_Unsigned func_len, fde_byte_len, fde_inst_len, bytes_in_cie;
	Dwarf_Unsigned cie_caf, cie_daf, cie_inst_len;
	Dwarf_Signed cie_index, opcnt;
	Dwarf_Off cie_offset, fde_offset;
	Dwarf_Ptr fde_bytes, fde_inst, cie_initinst;
	Dwarf_Half cie_ra;
	Dwarf_Small cie_version;
	Dwarf_Error de;
	const char *cfa_str;
	char *cie_augmenter;
	int i, j, r_fde_at_pc;

	if (eh) {
		if (dwarf_get_fde_list_eh(dbg, &cielist, &ciecnt, &fdelist,
		    &fdecnt, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_fde_list_eh failed: %s\n",
			    dwarf_errmsg(de));
			result = TET_FAIL;
			goto done;
		}
	} else {
		if (dwarf_get_fde_list(dbg, &cielist, &ciecnt, &fdelist,
		    &fdecnt, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_fde_list failed: %s\n",
			    dwarf_errmsg(de));
			result = TET_FAIL;
			goto done;
		}
	}
	TS_CHECK_INT(ciecnt);
	TS_CHECK_INT(fdecnt);

	/*
	 * Test dwarf_get_fde_at_pc using hard-coded PC values.
	 */

	tet_infoline("attempt to get fde at 0x08082a30");
	r_fde_at_pc = dwarf_get_fde_at_pc(fdelist, 0x08082a30, &fde, &low_pc,
	    &high_pc, &de);
	TS_CHECK_INT(r_fde_at_pc);
	if (r_fde_at_pc == DW_DLV_OK) {
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(high_pc);
	}

	tet_infoline("attempt to get fde at 0x08083087");
	r_fde_at_pc = dwarf_get_fde_at_pc(fdelist, 0x08083087, &fde, &low_pc,
	    &high_pc, &de);
	TS_CHECK_INT(r_fde_at_pc);
	if (r_fde_at_pc == DW_DLV_OK) {
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(high_pc);
	}

	tet_infoline("attempt to get fde at 0x080481f0");
	r_fde_at_pc = dwarf_get_fde_at_pc(fdelist, 0x080481f0, &fde, &low_pc,
	    &high_pc, &de);
	TS_CHECK_INT(r_fde_at_pc);
	if (r_fde_at_pc == DW_DLV_OK) {
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(high_pc);
	}

	tet_infoline("attempt to get fde at 0x08048564");
	r_fde_at_pc = dwarf_get_fde_at_pc(fdelist, 0x08048564, &fde, &low_pc,
	    &high_pc, &de);
	TS_CHECK_INT(r_fde_at_pc);
	if (r_fde_at_pc == DW_DLV_OK) {
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(high_pc);
	}

	tet_infoline("attempt to get fde at 0x00401280");
	r_fde_at_pc = dwarf_get_fde_at_pc(fdelist, 0x00401280, &fde, &low_pc,
	    &high_pc, &de);
	TS_CHECK_INT(r_fde_at_pc);
	if (r_fde_at_pc == DW_DLV_OK) {
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(high_pc);
	}

	tet_infoline("attempt to get fde at 0x004012b1");
	r_fde_at_pc = dwarf_get_fde_at_pc(fdelist, 0x004012b1, &fde, &low_pc,
	    &high_pc, &de);
	TS_CHECK_INT(r_fde_at_pc);
	if (r_fde_at_pc == DW_DLV_OK) {
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(high_pc);
	}

	/*
	 * Test each FDE contained in the FDE list.
	 */

	for (i = 0; i < fdecnt; i++) {
		if (dwarf_get_fde_n(fdelist, i, &fde, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_fde_n(%d) failed: %s\n", i,
			    dwarf_errmsg(de));
			result = TET_FAIL;
			continue;
		}
		if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_bytes,
		    &fde_byte_len, &cie_offset, &cie_index, &fde_offset,
		    &de) == DW_DLV_ERROR) {
			tet_printf("dwarf_get_fde_range(%d) failed: %s\n", i,
			    dwarf_errmsg(de));
			result = TET_FAIL;
			continue;
		}
		TS_CHECK_UINT(low_pc);
		TS_CHECK_UINT(func_len);
		TS_CHECK_UINT(fde_byte_len);
		if (fde_byte_len > 0)
			TS_CHECK_BLOCK(fde_bytes, fde_byte_len);
		TS_CHECK_INT(cie_offset);
		TS_CHECK_INT(cie_index);
		TS_CHECK_INT(fde_offset);
		if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_cie_of_fde(%d) failed: %s\n", i,
			    dwarf_errmsg(de));
			result = TET_FAIL;
			continue;
		}
		if (dwarf_get_cie_index(cie, &cie_index, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_cie_index(%d) failed: %s\n", i,
			    dwarf_errmsg(de));
			result = TET_FAIL;
			continue;
		}
		TS_CHECK_INT(cie_index);
		if (dwarf_get_cie_info(cie, &bytes_in_cie, &cie_version,
		    &cie_augmenter, &cie_caf, &cie_daf, &cie_ra, &cie_initinst,
		    &cie_inst_len, &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_cie_info(%d) failed: %s\n", i,
			    dwarf_errmsg(de));
			result = TET_FAIL;
			continue;
		}
		TS_CHECK_UINT(bytes_in_cie);
		TS_CHECK_UINT(cie_version);
		TS_CHECK_STRING(cie_augmenter);
		TS_CHECK_UINT(cie_caf);
		TS_CHECK_UINT(cie_daf);
		TS_CHECK_UINT(cie_ra);
		TS_CHECK_UINT(cie_inst_len);
		if (cie_inst_len > 0)
			TS_CHECK_BLOCK(cie_initinst, cie_inst_len);
		if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_inst_len,
		    &de) != DW_DLV_OK) {
			tet_printf("dwarf_get_fde_instr_bytes(%d) failed: %s\n",
			    i, dwarf_errmsg(de));
			result = TET_FAIL;
			continue;
		}
		TS_CHECK_UINT(fde_inst_len);
		if (fde_inst_len > 0) {
			TS_CHECK_BLOCK(fde_inst, fde_inst_len);
			if (dwarf_expand_frame_instructions(cie, fde_inst,
			    fde_inst_len, &oplist, &opcnt, &de) != DW_DLV_OK) {
				tet_printf("dwarf_expand_frame_instructions(%d)"
				    " failed: %s\n", i, dwarf_errmsg(de));
				result = TET_FAIL;
				continue;
			}
			TS_CHECK_INT(opcnt);
			for (j = 0; j < opcnt; j++) {
				TS_CHECK_UINT(oplist[j].fp_base_op);
				if (oplist[j].fp_base_op != 0) {
					if (dwarf_get_CFA_name(
					    oplist[j].fp_base_op << 6,
					    &cfa_str) != DW_DLV_OK) {
						tet_printf("dwarf_get_CFA_name"
						    " failed\n");
						continue;
					}
					TS_CHECK_STRING(cfa_str);
				}
				TS_CHECK_UINT(oplist[j].fp_extended_op);
				if (oplist[j].fp_extended_op != 0) {
					if (dwarf_get_CFA_name(
					    oplist[j].fp_extended_op,
					    &cfa_str) != DW_DLV_OK) {
						tet_printf("dwarf_get_CFA_name"
						    " failed\n");
						continue;
					}
					TS_CHECK_STRING(cfa_str);
				}
				TS_CHECK_UINT(oplist[j].fp_register);
				TS_CHECK_INT(oplist[j].fp_offset);
				TS_CHECK_INT(oplist[j].fp_instr_offset);
			}
		}
		_frame_test(dbg, fde, low_pc, func_len, cie_caf);
	}

done:
	return;
}
예제 #2
0
/*  Used by rqs (an IRIX application).
    Not needed except for that one application.
    Should be moved to its own source file since
    it is so rarely needed.
    Returns DW_DLV_OK if returns the arrays.
    Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?)
    Returns DW_DLV_ERROR if there is an error.

    Uses DW_FRAME_CFA_COL because IRIX is only DWARF2
    and that is what IRIX compilers and compatible
    compilers support on IRIX.
*/
int
_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
    Dwarf_Off ** offsetlist,
    Dwarf_Signed * returncount,
    Dwarf_Error * err)
{
    int retval = DW_DLV_OK;
    int res = DW_DLV_ERROR;
    Dwarf_Cie *cie_data = 0;
    Dwarf_Signed cie_count = 0;
    Dwarf_Fde *fde_data = 0;
    Dwarf_Signed fde_count = 0;
    Dwarf_Signed i = 0;
    Dwarf_Unsigned u = 0;
    Dwarf_Frame_Op *frame_inst = 0;
    Dwarf_Fde fdep = 0;
    Dwarf_Cie ciep = 0;
    Dwarf_Chain curr_chain = 0;
    Dwarf_Chain head_chain = 0;
    Dwarf_Chain prev_chain = 0;
    Dwarf_Arange arange = 0;
    Dwarf_Unsigned arange_count = 0;
    Dwarf_Addr *arange_addrs = 0;
    Dwarf_Off *arange_offsets = 0;

    res = dwarf_get_fde_list(dbg, &cie_data, &cie_count,
        &fde_data, &fde_count, err);
    if (res != DW_DLV_OK) {
        return res;
    }

    res = _dwarf_load_section(dbg, &dbg->de_debug_frame, err);
    if (res != DW_DLV_OK) {
        return res;
    }
    if (!dbg->de_debug_frame.dss_size) {
        return (DW_DLV_NO_ENTRY);
    }

    for (i = 0; i < cie_count; i++) {
        Dwarf_Off instoff = 0;
        Dwarf_Signed initial_instructions_length = 0;
        Dwarf_Small *instr_end = 0;
        Dwarf_Sword icount = 0;
        int j = 0;
        int dw_err;

        ciep = cie_data[i];
        instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame.dss_data;
        initial_instructions_length = ciep->ci_length +
            ciep->ci_length_size + ciep->ci_extension_size -
            (ciep->ci_cie_instr_start - ciep->ci_cie_start);
        instr_end = ciep->ci_cie_instr_start +
            initial_instructions_length;
        res = _dwarf_exec_frame_instr( /* make_instr */ true,
            &frame_inst,
            /* search_pc= */ false,
            /* search_pc_val= */ 0,
            /* location */ 0,
            ciep->ci_cie_instr_start,
            instr_end,
            /* Dwarf_frame= */ 0,
            /* cie= */ 0,
            dbg,
            DW_FRAME_CFA_COL,
            &icount, &dw_err);
        if (res == DW_DLV_ERROR) {
            _dwarf_error(dbg, err, dw_err);
            return (res);
        } else if (res == DW_DLV_NO_ENTRY) {
            continue;
        }

        for (j = 0; j < icount; ++j) {
            Dwarf_Frame_Op *finst = frame_inst + j;

            if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) {
                /* is DW_CFA_set_loc */
                Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset;
                Dwarf_Off off = finst->fp_instr_offset + instoff;

                arange = (Dwarf_Arange)
                    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
                if (arange == NULL) {
                    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
                    return (DW_DLV_ERROR);
                }
                arange->ar_address = add;
                arange->ar_info_offset = off;
                arange_count++;
                curr_chain = (Dwarf_Chain)
                    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
                if (curr_chain == NULL) {
                    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
                    return (DW_DLV_ERROR);
                }
                curr_chain->ch_item = arange;
                if (head_chain == NULL)
                    head_chain = prev_chain = curr_chain;
                else {
                    prev_chain->ch_next = curr_chain;
                    prev_chain = curr_chain;
                }
            }
        }
        dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);

    }
    for (i = 0; i < fde_count; i++) {
        Dwarf_Small *instr_end = 0;
        Dwarf_Sword icount = 0;
        Dwarf_Signed instructions_length = 0;
        Dwarf_Off instoff = 0;
        Dwarf_Off off = 0;
        Dwarf_Addr addr = 0;
        int j = 0;
        int dw_err;

        fdep = fde_data[i];
        off = fdep->fd_initial_loc_pos - dbg->de_debug_frame.dss_data;
        addr = fdep->fd_initial_location;
        arange = (Dwarf_Arange)
            _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
        if (arange == NULL) {
            _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
            return (DW_DLV_ERROR);
        }
        arange->ar_address = addr;
        arange->ar_info_offset = off;
        arange_count++;
        curr_chain = (Dwarf_Chain)
            _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
        if (curr_chain == NULL) {
            _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
            return (DW_DLV_ERROR);
        }
        curr_chain->ch_item = arange;
        if (head_chain == NULL)
            head_chain = prev_chain = curr_chain;
        else {
            prev_chain->ch_next = curr_chain;
            prev_chain = curr_chain;
        }


        instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame.dss_data;
        instructions_length = fdep->fd_length +
            fdep->fd_length_size + fdep->fd_extension_size -
            (fdep->fd_fde_instr_start - fdep->fd_fde_start);
        instr_end = fdep->fd_fde_instr_start + instructions_length;
        res = _dwarf_exec_frame_instr( /* make_instr */ true,
            &frame_inst,
            /* search_pc= */ false,
            /* search_pc_val= */ 0,
            /* location */ 0,
            fdep->fd_fde_instr_start,
            instr_end,
            /* Dwarf_frame= */ 0,
            /* cie= */ 0,
            dbg,
            DW_FRAME_CFA_COL,
            &icount, &dw_err);
        if (res == DW_DLV_ERROR) {
            _dwarf_error(dbg, err, dw_err);
            return (res);
        } else if (res == DW_DLV_NO_ENTRY) {
            continue;
        }

        for (j = 0; j < icount; ++j) {
            Dwarf_Frame_Op *finst2 = frame_inst + j;

            if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) {
                /* is DW_CFA_set_loc */
                Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset;
                Dwarf_Off off2 = finst2->fp_instr_offset + instoff;

                arange = (Dwarf_Arange)
                    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
                if (arange == NULL) {
                    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
                    return (DW_DLV_ERROR);
                }
                arange->ar_address = add;
                arange->ar_info_offset = off2;
                arange_count++;
                curr_chain = (Dwarf_Chain)
                    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
                if (curr_chain == NULL) {
                    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
                    return (DW_DLV_ERROR);
                }
                curr_chain->ch_item = arange;
                if (head_chain == NULL)
                    head_chain = prev_chain = curr_chain;
                else {
                    prev_chain->ch_next = curr_chain;
                    prev_chain = curr_chain;
                }

            }
        }
        dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);

    }
    dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
    dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
    arange_addrs = (Dwarf_Addr *)
        _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
    if (arange_addrs == NULL) {
        _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }
    arange_offsets = (Dwarf_Off *)
        _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
    if (arange_offsets == NULL) {
        _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }

    curr_chain = head_chain;
    for (u = 0; u < arange_count; u++) {
        Dwarf_Arange ar = curr_chain->ch_item;

        arange_addrs[u] = ar->ar_address;
        arange_offsets[u] = ar->ar_info_offset;
        prev_chain = curr_chain;
        curr_chain = curr_chain->ch_next;
        dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
        dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
    }
    *returncount = arange_count;
    *offsetlist = arange_offsets;
    *addrlist = arange_addrs;
    return retval;
}