Пример #1
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;
}
Пример #2
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);
}
Пример #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
/*  This function takes an Dwarf_Arange,
    and returns the offset of the CU header
    in the compilation-unit that the
    arange belongs to.  Returns DW_DLV_ERROR
    on error.   
    Ensures .debug_info loaded so
    the cu_offset is meaningful.  */
int
dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
    Dwarf_Off * cu_header_offset_returned,
    Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    if (arange == NULL) {
        _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
        return (DW_DLV_ERROR);
    }
    dbg = arange->ar_dbg;
    /* This applies to debug_info only, not to debug_types. */
    /*  Like dwarf_get_arange_info this ensures debug_info loaded:
        the cu_header is in debug_info and will be used else
        we would not call dwarf_get_arange_cu_header_offset. */
    if (!dbg->de_debug_info.dss_data) {
        int res = _dwarf_load_debug_info(dbg, error);
        if (res != DW_DLV_OK) {
            return res;
        }
    }
    *cu_header_offset_returned = arange->ar_info_offset;
    return DW_DLV_OK;
}
Пример #5
0
int
dwarf_get_abbrev(Dwarf_Debug dbg,
		 Dwarf_Unsigned offset,
		 Dwarf_Abbrev * returned_abbrev,
		 Dwarf_Unsigned * length,
		 Dwarf_Unsigned * abbr_count, Dwarf_Error * error)
{
    Dwarf_Small *abbrev_ptr;
    Dwarf_Small *abbrev_section_end;
    Dwarf_Half attr;
    Dwarf_Half attr_form;
    Dwarf_Abbrev ret_abbrev;
    Dwarf_Unsigned labbr_count = 0;
    Dwarf_Unsigned utmp;


    if (dbg == NULL) {
	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
	return (DW_DLV_ERROR);
    }
    if (dbg->de_debug_abbrev == 0) {
	/* Loads abbrev section (and .debug_info as we do those
	   together). */
	int res = _dwarf_load_debug_info(dbg, error);

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

    if (offset >= dbg->de_debug_abbrev_size) {
	return (DW_DLV_NO_ENTRY);
    }


    ret_abbrev = (Dwarf_Abbrev) _dwarf_get_alloc(dbg, DW_DLA_ABBREV, 1);
    if (ret_abbrev == NULL) {
	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (DW_DLV_ERROR);
    }
    ret_abbrev->ab_dbg = dbg;
    if (returned_abbrev == 0 || abbr_count == 0) {
	dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
	_dwarf_error(dbg, error, DW_DLE_DWARF_ABBREV_NULL);
	return (DW_DLV_ERROR);
    }


    *abbr_count = 0;
    if (length != NULL)
	*length = 1;

    abbrev_ptr = dbg->de_debug_abbrev + offset;
    abbrev_section_end =
	dbg->de_debug_abbrev + dbg->de_debug_abbrev_size;

    DECODE_LEB128_UWORD(abbrev_ptr, utmp);
    ret_abbrev->ab_code = (Dwarf_Word) utmp;
    if (ret_abbrev->ab_code == 0) {
	*returned_abbrev = ret_abbrev;
	*abbr_count = 0;
	if (length) {
	    *length = 1;
	}
	return (DW_DLV_OK);
    }

    DECODE_LEB128_UWORD(abbrev_ptr, utmp);
    ret_abbrev->ab_tag = utmp;
    ret_abbrev->ab_has_child = *(abbrev_ptr++);
    ret_abbrev->ab_abbrev_ptr = abbrev_ptr;

    do {
	Dwarf_Unsigned utmp2;

	DECODE_LEB128_UWORD(abbrev_ptr, utmp2)
	    attr = (Dwarf_Half) utmp2;
	DECODE_LEB128_UWORD(abbrev_ptr, utmp2)
	    attr_form = (Dwarf_Half) utmp2;

	if (attr != 0)
	    (labbr_count)++;

    } while (abbrev_ptr < abbrev_section_end &&
	     (attr != 0 || attr_form != 0));

    if (abbrev_ptr > abbrev_section_end) {
	dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
	_dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
	return (DW_DLV_ERROR);
    }

    if (length != NULL)
	*length = abbrev_ptr - dbg->de_debug_abbrev - offset;

    *returned_abbrev = ret_abbrev;
    *abbr_count = labbr_count;
    return (DW_DLV_OK);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
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;
}
Пример #9
0
/* Sweeps the complete  section.  */
int
_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
    Dwarf_Small * section_data_ptr,
    Dwarf_Unsigned section_length,
    Dwarf_Global ** globals,
    Dwarf_Signed * return_count,
    Dwarf_Error * error,
    int context_code,
    int global_code,
    int length_err_num,
    int version_err_num)
{
    Dwarf_Small *pubnames_like_ptr = 0;
    Dwarf_Small *section_end_ptr = section_data_ptr +section_length;

    /*  Points to the context for the current set of global names, and
        contains information to identify the compilation-unit that the
        set refers to. */
    Dwarf_Global_Context pubnames_context = 0;

    Dwarf_Half version = 0;

    /*  Offset from the start of compilation-unit for the current
        global. */
    Dwarf_Off die_offset_in_cu = 0;

    Dwarf_Unsigned global_count = 0;

    /* Points to the current global read. */
    Dwarf_Global global = 0;

    /*  Used to chain the Dwarf_Global_s structs for creating contiguous
        list of pointers to the structs. */
    Dwarf_Chain curr_chain = 0;
    Dwarf_Chain prev_chain = 0;
    Dwarf_Chain head_chain = 0;

    /* Points to contiguous block of Dwarf_Global's to be returned. */
    Dwarf_Global *ret_globals = 0;

    /* Temporary counter. */
    Dwarf_Unsigned i = 0;

    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
        return (DW_DLV_ERROR);
    }
    /* We will eventually need the .debug_info data. Load it now. */
    if (!dbg->de_debug_info.dss_data) {
        int res = _dwarf_load_debug_info(dbg, error);

        if (res != DW_DLV_OK) {
            return res;
        }
    }
    if (section_data_ptr == NULL) {
        return (DW_DLV_NO_ENTRY);
    }
    pubnames_like_ptr = section_data_ptr;
    do {
        Dwarf_Unsigned length = 0;
        int local_extension_size = 0;
        int local_length_size = 0;

        /*  Some compilers emit padding at the end of each cu's area.
            pubnames_ptr_past_end_cu records the true area end for the
            pubnames(like) content of a cu.
            Essentially the length in the header and the 0
            terminator of the data are redundant information. The
            dwarf2/3 spec does not mention what to do if the length is
            past the 0 terminator. So we take any bytes left after the 0
            as padding and ignore them. */
        Dwarf_Small *pubnames_ptr_past_end_cu = 0;


        pubnames_context = (Dwarf_Global_Context)
            _dwarf_get_alloc(dbg, context_code, 1);
        if (pubnames_context == NULL) {
            _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
        }
        /*  READ_AREA_LENGTH updates pubnames_like_ptr for consumed
            bytes. */
        READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned,
            pubnames_like_ptr, local_length_size,
            local_extension_size,error,section_length,section_end_ptr);
        pubnames_context->pu_length_size = local_length_size;
        pubnames_context->pu_extension_size = local_extension_size;
        pubnames_context->pu_dbg = dbg;

        pubnames_ptr_past_end_cu = pubnames_like_ptr + length;

        READ_UNALIGNED_CK(dbg, version, Dwarf_Half,
            pubnames_like_ptr, DWARF_HALF_SIZE,
            error,section_end_ptr);
        pubnames_like_ptr += DWARF_HALF_SIZE;
        /* ASSERT: DW_PUBNAMES_VERSION2 == DW_PUBTYPES_VERSION2 */
        if (version != DW_PUBNAMES_VERSION2) {
            _dwarf_error(dbg, error, version_err_num);
            return (DW_DLV_ERROR);
        }

        /* Offset of CU header in debug section. */
        READ_UNALIGNED_CK(dbg, pubnames_context->pu_offset_of_cu_header,
            Dwarf_Off, pubnames_like_ptr,
            pubnames_context->pu_length_size,
            error,section_end_ptr);
        pubnames_like_ptr += pubnames_context->pu_length_size;

        FIX_UP_OFFSET_IRIX_BUG(dbg,
            pubnames_context->pu_offset_of_cu_header,
            "pubnames cu header offset");


        READ_UNALIGNED_CK(dbg, pubnames_context->pu_info_length,
            Dwarf_Unsigned, pubnames_like_ptr,
            pubnames_context->pu_length_size,
            error,section_end_ptr);
        pubnames_like_ptr += pubnames_context->pu_length_size;

        if (pubnames_like_ptr > (section_data_ptr + section_length)) {
            _dwarf_error(dbg, error, length_err_num);
            return (DW_DLV_ERROR);
        }

        /*  Read initial offset (of DIE within CU) of a pubname, final
            entry is not a pair, just a zero offset. */
        READ_UNALIGNED_CK(dbg, die_offset_in_cu, Dwarf_Off,
            pubnames_like_ptr,
            pubnames_context->pu_length_size,
            error,section_end_ptr);
        pubnames_like_ptr += pubnames_context->pu_length_size;
        FIX_UP_OFFSET_IRIX_BUG(dbg,
            die_offset_in_cu, "offset of die in cu");

        /* Loop thru pairs. DIE off with CU followed by string. */
        while (die_offset_in_cu != 0) {
            int res;

            /*  Already read offset, pubnames_like_ptr now points to the
                string. */
            global =
                (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
            if (global == NULL) {
                _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (DW_DLV_ERROR);
            }
            global_count++;

            global->gl_context = pubnames_context;

            global->gl_named_die_offset_within_cu = die_offset_in_cu;

            global->gl_name = pubnames_like_ptr;

            res = _dwarf_check_string_valid(dbg,section_data_ptr,
                pubnames_like_ptr,section_end_ptr,
                DW_DLE_STRING_OFF_END_PUBNAMES_LIKE,error);
            if (res != DW_DLV_OK) {
                return res;
            }
            pubnames_like_ptr = pubnames_like_ptr +
                strlen((char *) pubnames_like_ptr) + 1;

            /* Finish off current entry chain */
            curr_chain =
                (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
            if (curr_chain == NULL) {
                _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (DW_DLV_ERROR);
            }

            /* Put current global on singly_linked list. */
            curr_chain->ch_item = (Dwarf_Global) global;

            if (head_chain == NULL)
                head_chain = prev_chain = curr_chain;
            else {
                prev_chain->ch_next = curr_chain;
                prev_chain = curr_chain;
            }

            /* Fead offset for the *next* entry */
            READ_UNALIGNED_CK(dbg, die_offset_in_cu, Dwarf_Off,
                pubnames_like_ptr, pubnames_context->pu_length_size,
                error,section_end_ptr);
            pubnames_like_ptr += pubnames_context->pu_length_size;
            FIX_UP_OFFSET_IRIX_BUG(dbg,
                die_offset_in_cu, "offset of next die in cu");
            if (pubnames_like_ptr > (section_data_ptr + section_length)) {
                _dwarf_error(dbg, error, length_err_num);
                return (DW_DLV_ERROR);
            }
        }
        /* ASSERT: die_offset_in_cu == 0 */
        if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
            /* This is some kind of error. This simply cannot happen.
            The encoding is wrong or the length in the header for
            this cu's contribution is wrong. */
            _dwarf_error(dbg, error, length_err_num);
            return (DW_DLV_ERROR);
        }
        /*  If there is some kind of padding at the end of the section,
            as emitted by some compilers, skip over that padding and
            simply ignore the bytes thus passed-over.  With most
            compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
            this point */
        pubnames_like_ptr = pubnames_ptr_past_end_cu;

    } while (pubnames_like_ptr < (section_data_ptr + section_length));

    /* Points to contiguous block of Dwarf_Global's. */
    ret_globals = (Dwarf_Global *)
        _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
    if (ret_globals == NULL) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }

    /*  Store pointers to Dwarf_Global_s structs in contiguous block,
        and deallocate the chain. */
    curr_chain = head_chain;
    for (i = 0; i < global_count; i++) {
        *(ret_globals + i) = curr_chain->ch_item;
        prev_chain = curr_chain;
        curr_chain = curr_chain->ch_next;
        dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
    }

    *globals = ret_globals;
    *return_count = (Dwarf_Signed) global_count;
    return DW_DLV_OK;
}
Пример #10
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);
}
Пример #11
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);
}