Beispiel #1
0
static int
dwarf_next_cu_header_internal(Dwarf_Debug dbg,
    Dwarf_Bool is_info,
    Dwarf_Unsigned * cu_header_length,
    Dwarf_Half * version_stamp,
    Dwarf_Unsigned * abbrev_offset,
    Dwarf_Half * address_size,
    Dwarf_Half * offset_size,
    Dwarf_Half * extension_size,
    Dwarf_Sig8 * signature,
    Dwarf_Unsigned *typeoffset,
    Dwarf_Unsigned * next_cu_offset,
    Dwarf_Error * error)
{
    /* Offset for current and new CU. */
    Dwarf_Unsigned new_offset = 0;

    /* CU Context for current CU. */
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug_InfoTypes dis = 0;
    Dwarf_Unsigned section_size =  0;



    /* ***** BEGIN CODE ***** */

    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
        return (DW_DLV_ERROR);
    }
    dis = is_info? &dbg->de_info_reading: &dbg->de_types_reading;
    /*  Get offset into .debug_info of next CU. If dbg has no context,
        this has to be the first one. */
    if (dis->de_cu_context == NULL) {
        new_offset = 0;
        Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
            dbg->de_debug_types.dss_data;
        if (!dataptr) {
            Dwarf_Error err2= 0;
            int res = is_info?_dwarf_load_debug_info(dbg, &err2):
                _dwarf_load_debug_types(dbg,&err2);

            if (res != DW_DLV_OK) {
                if(reloc_incomplete(err2)) {
                    /*  We will assume all is ok, though it is not. 
                        Relocation errors need not be fatal.  */
                    char msg_buf[200];
                    snprintf(msg_buf,sizeof(msg_buf),
                        "Relocations did not complete successfully, but we are "
                        " ignoring error: %s",dwarf_errmsg(err2));
                    dwarf_insert_harmless_error(dbg,msg_buf);
                    res = DW_DLV_OK;
                } else {
                    if( error) {
                        *error = err2;
                    }
                    return res;
                }
              
            }
        }

    } else {
        new_offset = dis->de_cu_context->cc_debug_offset +
            dis->de_cu_context->cc_length +
            dis->de_cu_context->cc_length_size +
            dis->de_cu_context->cc_extension_size;
    }

    /*  Check that there is room in .debug_info beyond the new offset
        for at least a new cu header. If not, return 0 to indicate end
        of debug_info section, and reset de_cu_debug_info_offset to
        enable looping back through the cu's. */
    section_size = is_info? dbg->de_debug_info.dss_size:
        dbg->de_debug_types.dss_size;
    if ((new_offset + _dwarf_length_of_cu_header_simple(dbg,is_info)) >= 
        section_size) {
        dis->de_cu_context = NULL;
        return (DW_DLV_NO_ENTRY);
    }

    /* Check if this CU has been read before. */
    cu_context = _dwarf_find_CU_Context(dbg, new_offset,is_info);

    /* If not, make CU Context for it. */
    if (cu_context == NULL) {
        cu_context = _dwarf_make_CU_Context(dbg, new_offset,is_info, error);
        if (cu_context == NULL) {
            /*  Error if CU Context could not be made. Since
                _dwarf_make_CU_Context has already registered an error
                we do not do that here: we let the lower error pass
                thru. */
            return (DW_DLV_ERROR);
        }
    }

    dis->de_cu_context = cu_context;

    if (cu_header_length != NULL) {
        *cu_header_length = cu_context->cc_length;
    }

    if (version_stamp != NULL) {
        *version_stamp = cu_context->cc_version_stamp;
    }
    if (abbrev_offset != NULL) {
        *abbrev_offset = cu_context->cc_abbrev_offset;
    }

    if (address_size != NULL) {
        *address_size = cu_context->cc_address_size;
    }
    if (offset_size != NULL) {
        *offset_size = cu_context->cc_length_size;
    }
    if (extension_size != NULL) {
        *extension_size = cu_context->cc_extension_size;
    }
    if(!is_info) {  
        if(signature) {
            *signature = cu_context->cc_signature;
        }
        if(typeoffset) {
            *typeoffset = cu_context->cc_typeoffset;
        }
    }

    new_offset = new_offset + cu_context->cc_length +
        cu_context->cc_length_size + cu_context->cc_extension_size;
    *next_cu_offset = new_offset;
    return (DW_DLV_OK);
}
Beispiel #2
0
/*
	Given a die offset, this returns
	a pointer to a DIE thru *new_die.
	It is up to the caller to do a
	dwarf_dealloc(dbg,*new_die,DW_DLE_DIE);
*/
int
dwarf_offdie(Dwarf_Debug dbg,
	     Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context;
    Dwarf_Off new_cu_offset = 0;
    Dwarf_Die die;
    Dwarf_Byte_Ptr info_ptr;
    Dwarf_Half abbrev_code;
    Dwarf_Unsigned utmp;

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

    cu_context = _dwarf_find_CU_Context(dbg, offset);
    if (cu_context == NULL)
	cu_context = _dwarf_find_offdie_CU_Context(dbg, offset);

    if (cu_context == NULL) {
	int res = _dwarf_load_debug_info(dbg, error);

	if (res != DW_DLV_OK) {
	    return res;
	}

	if (dbg->de_cu_context_list_end != NULL)
	    new_cu_offset =
		dbg->de_cu_context_list_end->cc_debug_info_offset +
		dbg->de_cu_context_list_end->cc_length +
		dbg->de_cu_context_list_end->cc_length_size +
		dbg->de_cu_context_list_end->cc_extension_size;

	do {
	    if ((new_cu_offset +
		 _dwarf_length_of_cu_header_simple(dbg)) >=
		dbg->de_debug_info_size) {
		_dwarf_error(dbg, error, DW_DLE_OFFSET_BAD);
		return (DW_DLV_ERROR);
	    }

	    cu_context =
		_dwarf_make_CU_Context(dbg, new_cu_offset, error);
	    if (cu_context == NULL) {
		/* Error if CU Context could not be made. Since
		   _dwarf_make_CU_Context has already registered an
		   error we do not do that here: we let the lower error
		   pass thru. */

		return (DW_DLV_ERROR);
	    }

	    if (dbg->de_offdie_cu_context == NULL) {
		dbg->de_offdie_cu_context = cu_context;
		dbg->de_offdie_cu_context_end = cu_context;
	    } else {
		dbg->de_offdie_cu_context_end->cc_next = cu_context;
		dbg->de_offdie_cu_context_end = cu_context;
	    }

	    new_cu_offset = new_cu_offset + cu_context->cc_length +
		cu_context->cc_length_size;

	} while (offset >= new_cu_offset);
    }

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

    info_ptr = dbg->de_debug_info + offset;
    die->di_debug_info_ptr = info_ptr;
    DECODE_LEB128_UWORD(info_ptr, utmp)
	abbrev_code = (Dwarf_Half) utmp;
    if (abbrev_code == 0) {
	/* we are at a null DIE (or there is a bug). */
	*new_die = 0;
	return DW_DLV_NO_ENTRY;
    }

    die->di_abbrev_list =
	_dwarf_get_abbrev_for_code(cu_context, abbrev_code);
    if (die->di_abbrev_list == NULL) {
	_dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
	return (DW_DLV_ERROR);
    }

    *new_die = die;
    return (DW_DLV_OK);
}
Beispiel #3
0
int
dwarf_offdie_b(Dwarf_Debug dbg,
    Dwarf_Off offset, Dwarf_Bool is_info, 
    Dwarf_Die * new_die, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Off new_cu_offset = 0;
    Dwarf_Die die = 0;
    Dwarf_Byte_Ptr info_ptr = 0;
    Dwarf_Unsigned abbrev_code = 0;
    Dwarf_Unsigned utmp = 0;
    Dwarf_Debug_InfoTypes dis = 0;


    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
        return (DW_DLV_ERROR);
    }
    dis = is_info? &dbg->de_info_reading:
        &dbg->de_types_reading;

    cu_context = _dwarf_find_CU_Context(dbg, offset,is_info);
    if (cu_context == NULL)
        cu_context = _dwarf_find_offdie_CU_Context(dbg, offset,is_info);

    if (cu_context == NULL) {
        Dwarf_Unsigned section_size = is_info? dbg->de_debug_info.dss_size:
            dbg->de_debug_types.dss_size;
        int res = is_info?_dwarf_load_debug_info(dbg, error):
            _dwarf_load_debug_types(dbg,error);

        if (res != DW_DLV_OK) {
            return res;
        }

        if (dis->de_offdie_cu_context_end != NULL) {
            Dwarf_CU_Context lcu_context =
                dis->de_offdie_cu_context_end;
            new_cu_offset =
                lcu_context->cc_debug_offset +
                lcu_context->cc_length +
                lcu_context->cc_length_size +
                lcu_context->cc_extension_size;
        }


        do {
            if ((new_cu_offset +
                _dwarf_length_of_cu_header_simple(dbg,is_info)) >= section_size) {
                _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD);
                return (DW_DLV_ERROR);
            }

            cu_context =
                _dwarf_make_CU_Context(dbg, new_cu_offset,is_info, error);
            if (cu_context == NULL) {
                /*  Error if CU Context could not be made. Since
                    _dwarf_make_CU_Context has already registered an
                    error we do not do that here: we let the lower error
                    pass thru. */

                return (DW_DLV_ERROR);
            }

            if (dis->de_offdie_cu_context == NULL) {
                dis->de_offdie_cu_context = cu_context;
                dis->de_offdie_cu_context_end = cu_context;
            } else {
                dis->de_offdie_cu_context_end->cc_next = cu_context;
                dis->de_offdie_cu_context_end = cu_context;
            }

            new_cu_offset = new_cu_offset + cu_context->cc_length +
                cu_context->cc_length_size;

        } while (offset >= new_cu_offset);
    }

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

    {
        Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
            dbg->de_debug_types.dss_data;
        info_ptr = dataptr + offset;
    }
    die->di_debug_ptr = info_ptr;
    DECODE_LEB128_UWORD(info_ptr, utmp);
    abbrev_code = utmp;
    if (abbrev_code == 0) {
        /* we are at a null DIE (or there is a bug). */
        *new_die = 0;
        dwarf_dealloc(dbg, die, DW_DLA_DIE);
        return DW_DLV_NO_ENTRY;
    }
    die->di_abbrev_code = abbrev_code;
    die->di_abbrev_list =
        _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
    if (die->di_abbrev_list == NULL) {
        dwarf_dealloc(dbg, die, DW_DLA_DIE);
        _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
        return (DW_DLV_ERROR);
    }

    *new_die = die;
    return (DW_DLV_OK);
}
Beispiel #4
0
/*
    Returns offset of next compilation-unit thru next_cu_offset
	pointer.
    It basically sequentially moves from one
    cu to the next.  The current cu is recorded
    internally by libdwarf.
*/
int
dwarf_next_cu_header(Dwarf_Debug dbg,
		     Dwarf_Unsigned * cu_header_length,
		     Dwarf_Half * version_stamp,
		     Dwarf_Unsigned * abbrev_offset,
		     Dwarf_Half * address_size,
		     Dwarf_Unsigned * next_cu_offset,
		     Dwarf_Error * error)
{
    /* Offset for current and new CU. */
    Dwarf_Unsigned new_offset;

    /* CU Context for current CU. */
    Dwarf_CU_Context cu_context;

    /* ***** BEGIN CODE ***** */

    if (dbg == NULL) {
	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
	return (DW_DLV_ERROR);
    }
    /* 
       Get offset into .debug_info of next CU. If dbg has no context,
       this has to be the first one. */
    if (dbg->de_cu_context == NULL) {
	new_offset = 0;
	if (!dbg->de_debug_info) {
	    int res = _dwarf_load_debug_info(dbg, error);

	    if (res != DW_DLV_OK) {
		return res;
	    }
	}

    } else {
	new_offset = dbg->de_cu_context->cc_debug_info_offset +
	    dbg->de_cu_context->cc_length +
	    dbg->de_cu_context->cc_length_size +
	    dbg->de_cu_context->cc_extension_size;
    }

    /* 
       Check that there is room in .debug_info beyond the new offset
       for at least a new cu header. If not, return 0 to indicate end
       of debug_info section, and reset de_cu_debug_info_offset to
       enable looping back through the cu's. */
    if ((new_offset + _dwarf_length_of_cu_header_simple(dbg)) >=
	dbg->de_debug_info_size) {
	dbg->de_cu_context = NULL;
	return (DW_DLV_NO_ENTRY);
    }

    /* Check if this CU has been read before. */
    cu_context = _dwarf_find_CU_Context(dbg, new_offset);

    /* If not, make CU Context for it. */
    if (cu_context == NULL) {
	cu_context = _dwarf_make_CU_Context(dbg, new_offset, error);
	if (cu_context == NULL) {
	    /* Error if CU Context could not be made. Since
	       _dwarf_make_CU_Context has already registered an error
	       we do not do that here: we let the lower error pass
	       thru. */
	    return (DW_DLV_ERROR);
	}
    }

    dbg->de_cu_context = cu_context;

    if (cu_header_length != NULL)
	*cu_header_length = cu_context->cc_length;

    if (version_stamp != NULL)
	*version_stamp = cu_context->cc_version_stamp;

    if (abbrev_offset != NULL)
	*abbrev_offset = cu_context->cc_abbrev_offset;

    if (address_size != NULL)
	*address_size = cu_context->cc_address_size;

    new_offset = new_offset + cu_context->cc_length +
	cu_context->cc_length_size + cu_context->cc_extension_size;
    *next_cu_offset = new_offset;
    return (DW_DLV_OK);
}