示例#1
0
int
dwarf_child(Dwarf_Die die,
    Dwarf_Die * caller_ret_die, Dwarf_Error * error)
{
    Dwarf_Byte_Ptr die_info_ptr = 0;

    /* die_info_end points one-past-end of die area. */
    Dwarf_Byte_Ptr die_info_end = 0;
    Dwarf_Die ret_die = 0;
    Dwarf_Bool has_die_child = 0;
    Dwarf_Debug dbg;
    Dwarf_Word abbrev_code = 0;
    Dwarf_Unsigned utmp = 0;
    Dwarf_Small *dataptr = 0;
    Dwarf_Debug_InfoTypes dis = 0;

    CHECK_DIE(die, DW_DLV_ERROR);
    dbg = die->di_cu_context->cc_dbg;
    dis = die->di_is_info? &dbg->de_info_reading: 
        &dbg->de_types_reading; 
    die_info_ptr = die->di_debug_ptr;

    dataptr = die->di_is_info? dbg->de_debug_info.dss_data:
        dbg->de_debug_types.dss_data;


    /*  We are saving a DIE pointer here, but the pointer
        will not be presumed live later, when it is tested. */
    dis->de_last_die = die;
    dis->de_last_di_ptr = die_info_ptr;

    /* NULL die has no child. */
    if ((*die_info_ptr) == 0)
        return (DW_DLV_NO_ENTRY);

    die_info_end = dataptr +
        die->di_cu_context->cc_debug_offset +
        die->di_cu_context->cc_length +
        die->di_cu_context->cc_length_size +
        die->di_cu_context->cc_extension_size;

    die_info_ptr =
        _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context,
            die_info_end, NULL, false,
            &has_die_child);
    if (die_info_ptr == NULL) {
        _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
        return (DW_DLV_ERROR);
    }

    dis->de_last_di_ptr = die_info_ptr;

    if (!has_die_child) {
        /* Look for end of sibling chain. */
        while ( dis->de_last_di_ptr < die_info_end) {
            if (*dis->de_last_di_ptr) {
                break;
            }
            ++dis->de_last_di_ptr;
        }
        return (DW_DLV_NO_ENTRY);
    }

    ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
    if (ret_die == NULL) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }
    ret_die->di_debug_ptr = die_info_ptr;
    ret_die->di_cu_context = die->di_cu_context;
    ret_die->di_is_info = die->di_is_info;

    DECODE_LEB128_UWORD(die_info_ptr, utmp);
    abbrev_code = (Dwarf_Word) utmp;

    dis->de_last_di_ptr = die_info_ptr;

    if (abbrev_code == 0) {
        /* Look for end of sibling chain */
        while ( dis->de_last_di_ptr < die_info_end) {
            if (*dis->de_last_di_ptr) {
                break;
            }
            ++dis->de_last_di_ptr;
        }

        /*  We have arrived at a null DIE, at the end of a CU or the end 
            of a list of siblings. */
        *caller_ret_die = 0;
        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
        return DW_DLV_NO_ENTRY;
    }
    ret_die->di_abbrev_code = abbrev_code;
    ret_die->di_abbrev_list =
        _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code);
    if (ret_die->di_abbrev_list == NULL) {
        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
        _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
        return (DW_DLV_ERROR);
    }

    *caller_ret_die = ret_die;
    return (DW_DLV_OK);
}
示例#2
0
int
dwarf_child(Dwarf_Die die,
	    Dwarf_Die * caller_ret_die, Dwarf_Error * error)
{
    Dwarf_Byte_Ptr die_info_ptr;
    Dwarf_Byte_Ptr die_info_end;
    Dwarf_Die ret_die;
    Dwarf_Bool has_die_child;
    Dwarf_Debug dbg;
    Dwarf_Half abbrev_code;
    Dwarf_Unsigned utmp;


    CHECK_DIE(die, DW_DLV_ERROR)
	dbg = die->di_cu_context->cc_dbg;
    die_info_ptr = die->di_debug_info_ptr;

    /* NULL die has no child. */
    if ((*die_info_ptr) == 0)
	return (DW_DLV_NO_ENTRY);

    die_info_end = dbg->de_debug_info +
	die->di_cu_context->cc_debug_info_offset +
	die->di_cu_context->cc_length +
	die->di_cu_context->cc_length_size +
	die->di_cu_context->cc_extension_size;

    die_info_ptr =
	_dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context,
				 die_info_end, NULL, false,
				 &has_die_child);
    if (die_info_ptr == NULL) {
	_dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
	return (DW_DLV_ERROR);
    }

    if (!has_die_child)
	return (DW_DLV_NO_ENTRY);

    ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
    if (ret_die == NULL) {
	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (DW_DLV_ERROR);
    }
    ret_die->di_debug_info_ptr = die_info_ptr;
    ret_die->di_cu_context = die->di_cu_context;

    DECODE_LEB128_UWORD(die_info_ptr, utmp)
	abbrev_code = (Dwarf_Half) utmp;
    if (abbrev_code == 0) {
	/* We have arrived at a null DIE, at the end of a CU or the end 
	   of a list of siblings. */
	*caller_ret_die = 0;
	return DW_DLV_NO_ENTRY;
    }
    ret_die->di_abbrev_list =
	_dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code);
    if (ret_die->di_abbrev_list == NULL) {
	_dwarf_error(dbg, error, DW_DLE_DIE_BAD);
	return (DW_DLV_ERROR);
    }

    *caller_ret_die = ret_die;
    return (DW_DLV_OK);
}
示例#3
0
/*  This is the new form, October 2011.  On calling with 'die' NULL,
    we cannot tell if this is debug_info or debug_types, so 
    we must be informed!. */ 
int
dwarf_siblingof_b(Dwarf_Debug dbg,
    Dwarf_Die die,
    Dwarf_Bool is_info,
    Dwarf_Die * caller_ret_die, Dwarf_Error * error)
{
    Dwarf_Die ret_die = 0;
    Dwarf_Byte_Ptr die_info_ptr = 0;
    Dwarf_Byte_Ptr cu_info_start = 0;

    /* die_info_end points 1-past end of die (once set) */
    Dwarf_Byte_Ptr die_info_end = 0;
    Dwarf_Word abbrev_code = 0;
    Dwarf_Unsigned utmp = 0;
    /* Since die may be NULL, we rely on the input argument. */
    Dwarf_Debug_InfoTypes dis = is_info? &dbg->de_info_reading: 
        &dbg->de_types_reading; 
    Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
        dbg->de_debug_types.dss_data;

   

    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
        return (DW_DLV_ERROR);
    }

    if (die == NULL) {
        /*  Find root die of cu */
        /*  die_info_end is untouched here, need not be set in this
            branch. */
        Dwarf_Off off2;
        Dwarf_CU_Context context=0;

        /*  If we've not loaded debug_info, de_cu_context will be NULL,
            so no need to laod */

        context = dis->de_cu_context;
        if (context == NULL) {
            _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT);
            return (DW_DLV_ERROR);
        }

        off2 = context->cc_debug_offset;
        cu_info_start = dataptr + off2;
        die_info_ptr = cu_info_start +
            _dwarf_length_of_cu_header(dbg, off2,is_info);
        die_info_end = cu_info_start + context->cc_length +
            context->cc_length_size +
            context->cc_extension_size;
    } else {
        /* Find sibling die. */
        Dwarf_Bool has_child = false;
        Dwarf_Sword child_depth = 0;
        Dwarf_CU_Context context=0;

        /*  We cannot have a legal die unless debug_info was loaded, so
            no need to load debug_info here. */
        CHECK_DIE(die, DW_DLV_ERROR);

        die_info_ptr = die->di_debug_ptr;
        if (*die_info_ptr == 0) {
            return (DW_DLV_NO_ENTRY);
        }
        context = die->di_cu_context;
        cu_info_start = dataptr+ context->cc_debug_offset;
        die_info_end = cu_info_start + context->cc_length +
            context->cc_length_size +
            context->cc_extension_size;

        if ((*die_info_ptr) == 0) {
            return (DW_DLV_NO_ENTRY);
        }
        child_depth = 0;
        do {
            die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr,
                die->di_cu_context, die_info_end,
                cu_info_start, true, &has_child);
            if (die_info_ptr == NULL) {
                _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
                return (DW_DLV_ERROR);
            }

            /*  die_info_end is one past end. Do not read it!  
                A test for ``!= die_info_end''  would work as well,
                but perhaps < reads more like the meaning. */
            if(die_info_ptr < die_info_end) { 
                if ((*die_info_ptr) == 0 && has_child) {
                    die_info_ptr++;
                    has_child = false;
                }
            }

            /* die_info_ptr can be one-past-end. */
            if ((die_info_ptr == die_info_end) ||
                ((*die_info_ptr) == 0)) {
                for (; child_depth > 0 && *die_info_ptr == 0;
                    child_depth--, die_info_ptr++);
            } else {
                child_depth = has_child ? child_depth + 1 : child_depth;
            }

        } while (child_depth != 0);
    }

    /*  die_info_ptr > die_info_end is really a bug (possibly in dwarf
        generation)(but we are past end, no more DIEs here), whereas
        die_info_ptr == die_info_end means 'one past end, no more DIEs
        here'. */
    if (die_info_ptr >= die_info_end) {
        return (DW_DLV_NO_ENTRY);
    }

    if ((*die_info_ptr) == 0) {
        return (DW_DLV_NO_ENTRY);
    }

    ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
    if (ret_die == NULL) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }

    ret_die->di_is_info = is_info;
    ret_die->di_debug_ptr = die_info_ptr;
    ret_die->di_cu_context =
        die == NULL ? dis->de_cu_context : die->di_cu_context;

    DECODE_LEB128_UWORD(die_info_ptr, utmp);
    if (die_info_ptr > die_info_end) {
        /*  We managed to go past the end of the CU!. 
            Something is badly wrong. */
        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
        _dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
        return (DW_DLV_ERROR);
    }
    abbrev_code = (Dwarf_Word) utmp;
    if (abbrev_code == 0) {
        /* Zero means a null DIE */
        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
        return (DW_DLV_NO_ENTRY);
    }
    ret_die->di_abbrev_code = abbrev_code;
    ret_die->di_abbrev_list =
        _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code);
    if (ret_die->di_abbrev_list == NULL ) {
        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
        _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
        return (DW_DLV_ERROR);
    }
    if (die == NULL && !is_cu_tag(ret_die->di_abbrev_list->ab_tag)) { 
        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
        _dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU);
        return (DW_DLV_ERROR);
    }

    *caller_ret_die = ret_die;
    return (DW_DLV_OK);
}
示例#4
0
/*
    Given a Dwarf_Debug dbg, and a Dwarf_Die die, it returns 
    a Dwarf_Die for the sibling of die.  In case die is NULL, 
    it returns (thru ptr) a Dwarf_Die for the first die in the current 
    cu in dbg.  Returns DW_DLV_ERROR on error.

    It is assumed that every sibling chain including those with 
    only one element is terminated with a NULL die, except a 
    chain with only a NULL die.

    The algorithm moves from one die to the adjacent one.  It 
    returns when the depth of children it sees equals the number 
    of sibling chain terminations.  A single count, child_depth 
    is used to track the depth of children and sibling terminations 
    encountered.  Child_depth is incremented when a die has the 
    Has-Child flag set unless the child happens to be a NULL die.  
    Child_depth is decremented when a die has Has-Child false, 
    and the adjacent die is NULL.  Algorithm returns when 
    child_depth is 0.

    **NOTE: Do not modify input die, since it is used at the end.
*/
int
dwarf_siblingof(Dwarf_Debug dbg,
		Dwarf_Die die,
		Dwarf_Die * caller_ret_die, Dwarf_Error * error)
{
    Dwarf_Die ret_die;
    Dwarf_Byte_Ptr die_info_ptr;
    Dwarf_Byte_Ptr cu_info_start = 0;
    Dwarf_Byte_Ptr die_info_end = 0;
    Dwarf_Half abbrev_code;
    Dwarf_Unsigned utmp;


    if (dbg == NULL) {
	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
	return (DW_DLV_ERROR);
    }

    if (die == NULL) {
	/* Find root die of cu */
	/* die_info_end is untouched here, need not be set in this
	   branch. */
	Dwarf_Off off2;

	/* If we've not loaded debug_info, de_cu_context will be NULL,
	   so no need to laod */

	if (dbg->de_cu_context == NULL) {
	    _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT);
	    return (DW_DLV_ERROR);
	}

	off2 = dbg->de_cu_context->cc_debug_info_offset;
	die_info_ptr = dbg->de_debug_info +
	    off2 + _dwarf_length_of_cu_header(dbg, off2);
    } else {
	/* Find sibling die. */
	Dwarf_Bool has_child;
	Dwarf_Sword child_depth;

	/* We cannot have a legal die unless debug_info was loaded, so
	   no need to load debug_info here. */
	CHECK_DIE(die, DW_DLV_ERROR)

	    die_info_ptr = die->di_debug_info_ptr;
	if (*die_info_ptr == 0) {
	    return (DW_DLV_NO_ENTRY);
	}
	cu_info_start = dbg->de_debug_info +
	    die->di_cu_context->cc_debug_info_offset;
	die_info_end = cu_info_start + die->di_cu_context->cc_length +
	    die->di_cu_context->cc_length_size +
	    die->di_cu_context->cc_extension_size;

	if ((*die_info_ptr) == 0) {
	    return (DW_DLV_NO_ENTRY);
	}
	child_depth = 0;
	do {
	    die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr,
						    die->di_cu_context,
						    die_info_end,
						    cu_info_start, true,
						    &has_child);
	    if (die_info_ptr == NULL) {
		_dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
		return (DW_DLV_ERROR);
	    }

	    if ((*die_info_ptr) == 0 && has_child) {
		die_info_ptr++;
		has_child = false;
	    }

	    if ((*die_info_ptr) == 0)
		for (; child_depth > 0 && *die_info_ptr == 0;
		     child_depth--, die_info_ptr++);
	    else
		child_depth = has_child ? child_depth + 1 : child_depth;

	} while (child_depth != 0);
    }

    if (die != NULL && die_info_ptr >= die_info_end) {
	return (DW_DLV_NO_ENTRY);
    }

    if ((*die_info_ptr) == 0) {
	return (DW_DLV_NO_ENTRY);
    }

    ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
    if (ret_die == NULL) {
	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (DW_DLV_ERROR);
    }

    ret_die->di_debug_info_ptr = die_info_ptr;
    ret_die->di_cu_context =
	die == NULL ? dbg->de_cu_context : die->di_cu_context;

    DECODE_LEB128_UWORD(die_info_ptr, utmp)
	abbrev_code = (Dwarf_Half) utmp;
    if (abbrev_code == 0) {
	/* Zero means a null DIE */
	return (DW_DLV_NO_ENTRY);
    }
    ret_die->di_abbrev_list =
	_dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code);
    if (ret_die->di_abbrev_list == NULL || (die == NULL &&
					    ret_die->di_abbrev_list->
					    ab_tag !=
					    DW_TAG_compile_unit)) {
	_dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU);
	return (DW_DLV_ERROR);
    }

    *caller_ret_die = ret_die;
    return (DW_DLV_OK);
}