示例#1
0
/*
    This function takes a Dwarf_Arange, and returns
    true if it is not NULL.  It also stores the start
    address of the range in *start, the length of the
    range in *length, and the offset of the first die
    in the compilation-unit in *cu_die_offset.  It
    returns false on error.
    If cu_die_offset returned ensures .debug_info loaded so
    the cu_die_offset is meaningful.
*/
int
dwarf_get_arange_info(Dwarf_Arange arange,
    Dwarf_Addr * start,
    Dwarf_Unsigned * length,
    Dwarf_Off * cu_die_offset, Dwarf_Error * error)
{
    if (arange == NULL) {
        _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
        return (DW_DLV_ERROR);
    }

    if (start != NULL)
        *start = arange->ar_address;
    if (length != NULL)
        *length = arange->ar_length;
    if (cu_die_offset != NULL) {
        Dwarf_Debug dbg = arange->ar_dbg;
        Dwarf_Off offset = arange->ar_info_offset;

        /* This applies to debug_info only, not to debug_types. */
        if (!dbg->de_debug_info.dss_data) {
            int res = _dwarf_load_debug_info(dbg, error);
            if (res != DW_DLV_OK) {
                return res;
            }
        }
        *cu_die_offset =
            offset + _dwarf_length_of_cu_header(dbg, offset,true);
    }
    return (DW_DLV_OK);
}
示例#2
0
/*
    This function takes an Dwarf_Arange,
    and returns the offset of the first
    die in the compilation-unit that the
    arange belongs to.  Returns DW_DLV_ERROR
    on error.
*/
int
dwarf_get_cu_die_offset(Dwarf_Arange arange,
			Dwarf_Off * returned_offset,
			Dwarf_Error * error)
{
    Dwarf_Debug dbg;
    Dwarf_Off offset;

    if (arange == NULL) {
	_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
	return (DW_DLV_ERROR);
    }


    dbg = arange->ar_dbg;


    offset = arange->ar_info_offset;
    if(!dbg->de_debug_info) {
        int res = _dwarf_load_debug_info(dbg,error);
        if(res != DW_DLV_OK) {
	    return res;
        }
    }

    *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset);
    return DW_DLV_OK;
}
示例#3
0
/*
    This function takes an Dwarf_Arange,
    and returns the offset of the first
    die in the compilation-unit that the
    arange belongs to.  Returns DW_DLV_ERROR
    on error.

    For an arange, the cu_die can only be from debug_info,
    not debug_types, it seems.
*/
int
dwarf_get_cu_die_offset(Dwarf_Arange arange,
    Dwarf_Off * returned_offset,
    Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Off offset = 0;

    if (arange == NULL) {
        _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
        return (DW_DLV_ERROR);
    }
    dbg = arange->ar_dbg;
    offset = arange->ar_info_offset;
    /* This applies to debug_info only, not to debug_types. */
    if (!dbg->de_debug_info.dss_data) {
        int res = _dwarf_load_debug_info(dbg, error);

        if (res != DW_DLV_OK) {
            return res;
        }
    }
    *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset, true);
    return DW_DLV_OK;
}
示例#4
0
/*
  Give back the pubnames entry (or any other like section)
  name, symbol DIE offset, and the cu-DIE offset.
*/
int
dwarf_global_name_offsets (
    Dwarf_Global	global,
    char               **ret_name,
    Dwarf_Off		*die_offset,
    Dwarf_Off		*cu_die_offset,
    Dwarf_Error		*error
)
{
    Dwarf_Global_Context con;
    Dwarf_Off off;
    if (global == NULL)
	{_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL); return(DW_DLV_ERROR);}

    con = global->gl_context;
    if (con == NULL) 
	{_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL); 
	return(DW_DLV_ERROR);}

    off = con->pu_offset_of_cu_header;
    if (die_offset != NULL) {
	*die_offset = global->gl_named_die_offset_within_cu + off;
    }

    if (cu_die_offset != NULL) {
	*cu_die_offset = off + 
          _dwarf_length_of_cu_header(global->gl_context->pu_dbg, off);
    }

    *ret_name = (char *)global->gl_name;
    return DW_DLV_OK;
}
示例#5
0
/* ARGSUSED */
int
dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
    Dwarf_Off in_cu_header_offset,
    Dwarf_Off * out_cu_die_offset,
    UNUSEDARG Dwarf_Error * err)
{
    Dwarf_Off headerlen = 0;
    int cres = 0;

    cres = _dwarf_length_of_cu_header(dbg, in_cu_header_offset,true,
        &headerlen,err);
    if (cres != DW_DLV_OK) {
        return cres;
    }
    *out_cu_die_offset = in_cu_header_offset + headerlen;
    return DW_DLV_OK;
}
示例#6
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);
}
示例#7
0
/*
  Give back the pubnames entry (or any other like section)
  name, symbol DIE offset, and the cu-DIE offset.

  Various errors are possible.

  The string pointer returned thru ret_name is not
  dwarf_get_alloc()ed, so no dwarf_dealloc()
  DW_DLA_STRING should be applied to it.

*/
int
dwarf_global_name_offsets(Dwarf_Global global,
    char **ret_name,
    Dwarf_Off * die_offset,
    Dwarf_Off * cu_die_offset,
    Dwarf_Error * error)
{
    Dwarf_Global_Context con = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_Off off = 0;

    if (global == NULL) {
        _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
        return (DW_DLV_ERROR);
    }

    con = global->gl_context;

    if (con == NULL) {
        _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
        return (DW_DLV_ERROR);
    }

    off = con->pu_offset_of_cu_header;
    /*  The offset had better not be too close to the end. If it is,
        _dwarf_length_of_cu_header() will step off the end and therefore
        must not be used. 10 is a meaningless heuristic, but no CU
        header is that small so it is safe. An erroneous offset is due
        to a bug in the tool chain. A bug like this has been seen on
        IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
        with 2 million pubnames entries. */
#define MIN_CU_HDR_SIZE 10
    dbg = con->pu_dbg;
    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
        return (DW_DLV_ERROR);
    }
    /* Cannot refer to debug_types */
    if (dbg->de_debug_info.dss_size &&
        ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) {
        _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
        return (DW_DLV_ERROR);
    }
#undef MIN_CU_HDR_SIZE
    if (die_offset != NULL) {
        *die_offset = global->gl_named_die_offset_within_cu + off;
    }

    *ret_name = (char *) global->gl_name;

    if (cu_die_offset != NULL) {
        /* Globals cannot refer to debug_types */
        int cres = 0;
        Dwarf_Unsigned headerlen = 0;
        int res = _dwarf_load_debug_info(dbg, error);

        if (res != DW_DLV_OK) {
            return res;
        }
        /*  The offset had better not be too close to the end. If it is,
            _dwarf_length_of_cu_header() will step off the end and
            therefore must not be used. 10 is a meaningless heuristic,
            but no CU header is that small so it is safe. */
        /* Globals cannot refer to debug_types */
        if ((off + 10) >= dbg->de_debug_info.dss_size) {
            _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }
        cres = _dwarf_length_of_cu_header(dbg, off,true,
            &headerlen,error);
        if(cres != DW_DLV_OK) {
            return cres;
        }
        *cu_die_offset = off + headerlen;
    }
    return DW_DLV_OK;
}
示例#8
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);
}