Exemple #1
0
int
dwarf_formaddr(Dwarf_Attribute attr,
    Dwarf_Addr * return_addr, Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Addr ret_addr = 0;
    Dwarf_CU_Context cu_context = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) { 
        return res;
    } 
    if (attr->ar_attribute_form == DW_FORM_addr
        /*  || attr->ar_attribute_form == DW_FORM_ref_addr Allowance of
            DW_FORM_ref_addr was a mistake. The value returned in that
            case is NOT an address it is a global debug_info offset (ie, 
            not CU-relative offset within the CU in debug_info). The
            Dwarf document refers to it as an address (misleadingly) in
            sec 6.5.4 where it describes the reference form. It is
            address-sized so that the linker can easily update it, but
            it is a reference inside the debug_info section. No longer
            allowed. */
        ) {

        READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr,
            attr->ar_debug_ptr, 
            cu_context->cc_address_size);
        *return_addr = ret_addr;
        return (DW_DLV_OK);
    }

    _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
    return (DW_DLV_ERROR);
}
Exemple #2
0
int
dwarf_formexprloc(Dwarf_Attribute attr,
    Dwarf_Unsigned * return_exprlen, 
    Dwarf_Ptr  * block_ptr,
    Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) { 
        return res;
    } 
    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
        return (DW_DLV_ERROR);
    }
    if (attr->ar_attribute_form == DW_FORM_exprloc ) {
        Dwarf_Word leb_len = 0;
        Dwarf_Unsigned exprlen =
            (_dwarf_decode_u_leb128(attr->ar_debug_ptr, &leb_len));
        Dwarf_Small * addr = attr->ar_debug_ptr;
        *return_exprlen = exprlen;
        *block_ptr = addr + leb_len;
        return DW_DLV_OK;

    }
    _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD);
    return (DW_DLV_ERROR);
}
Exemple #3
0
/*  dwarf_formsig8 returns in the caller-provided 8 byte area
    the 8 bytes of a DW_FORM_ref_sig8 (copying the bytes
    directly to the caller).  Not a string, an 8 byte
    MD5 hash.  This function is new in DWARF4 libdwarf.
*/
int dwarf_formsig8(Dwarf_Attribute attr,
    Dwarf_Sig8 * returned_sig_bytes,
    Dwarf_Error*     error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned field_end_offset = 0;
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Small *dataptr = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) { 
        return res;
    } 

    if (attr->ar_attribute_form != DW_FORM_ref_sig8 ) {
        _dwarf_error(dbg, error, DW_DLE_BAD_REF_SIG8_FORM);
        return (DW_DLV_ERROR);
    }

    dataptr = cu_context->cc_is_info? dbg->de_debug_info.dss_data:
        dbg->de_debug_types.dss_data;

    field_end_offset = attr->ar_debug_ptr + sizeof(Dwarf_Sig8) -
        (dataptr + cu_context->cc_debug_offset);
    /* Check that offset is within current cu portion of .debug_info. */
    if (field_end_offset > cu_context->cc_length +
        cu_context->cc_length_size + cu_context->cc_extension_size) {
        _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD);
        return (DW_DLV_ERROR);
    }
  
    memcpy(returned_sig_bytes, attr->ar_debug_ptr, 
        sizeof(Dwarf_Sig8));
    return DW_DLV_OK;
}
Exemple #4
0
/*  Part of DebugFission.  So a dwarf dumper application
    can get the index and print it for the user.
    A convenience function.  New May 2014*/
int
dwarf_get_debug_str_index(Dwarf_Attribute attr,
    Dwarf_Unsigned *return_index,
    Dwarf_Error *error)
{
    int theform = attr->ar_attribute_form;
    if (theform == DW_FORM_strx ||
        theform == DW_FORM_GNU_str_index) {
        Dwarf_Unsigned index = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Small *info_ptr = attr->ar_debug_ptr;
        index = _dwarf_decode_u_leb128(info_ptr,&uleblen);
        *return_index = index;
        return DW_DLV_OK;
    }
    {
        Dwarf_CU_Context cu_context = 0;
        Dwarf_Debug dbg = 0;
        int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_NOT_ADDR_INDEX);
    }
    return (DW_DLV_ERROR);
}
Exemple #5
0
int
dwarf_get_debug_addr_index(Dwarf_Attribute attr,
    Dwarf_Unsigned * return_index,
    Dwarf_Error * error)
{
    int theform = attr->ar_attribute_form;
    if (theform == DW_FORM_GNU_addr_index ||
        theform == DW_FORM_addrx) {
        int res = 0;
        Dwarf_Unsigned index = 0;
        res = _dwarf_get_addr_index_itself(theform,
            attr->ar_debug_ptr,&index,error);
        *return_index = index;
        return res;
    }

    {
        Dwarf_CU_Context cu_context = 0;
        Dwarf_Debug dbg = 0;
        int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        _dwarf_error(dbg, error,
            DW_DLE_ATTR_FORM_NOT_ADDR_INDEX);
        return (DW_DLV_ERROR);
    }
    return DW_DLV_NO_ENTRY;
}
Exemple #6
0
/*
    This function is analogous to dwarf_whatform.
    It returns the attribute in attr instead of
    the form.
*/
int
dwarf_whatattr(Dwarf_Attribute attr,
    Dwarf_Half * return_attr, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;

    int res  =get_attr_dbg(&dbg,&cu_context, attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    *return_attr = (attr->ar_attribute);
    return DW_DLV_OK;
}
Exemple #7
0
int
dwarf_whatform(Dwarf_Attribute attr,
    Dwarf_Half * return_form, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;

    int res  =get_attr_dbg(&dbg,&cu_context, attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    *return_form = attr->ar_attribute_form;
    return (DW_DLV_OK);
}
Exemple #8
0
int
dwarf_hasform(Dwarf_Attribute attr,
    Dwarf_Half form,
    Dwarf_Bool * return_bool, Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;

    int res  =get_attr_dbg(&dbg,&cu_context, attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    *return_bool = (attr->ar_attribute_form == form);
    return DW_DLV_OK;
}
Exemple #9
0
/*  Convert an offset within the local CU into a section-relative
    debug_info (or debug_types) offset.
    See dwarf_global_formref() and dwarf_formref()
    for additional information on conversion rules.
*/
int
dwarf_convert_to_global_offset(Dwarf_Attribute attr,
    Dwarf_Off offset, Dwarf_Off * ret_offset, Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;
    int res = 0;

    res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    switch (attr->ar_attribute_form) {
    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref8:
    case DW_FORM_ref_udata:
        /*  It is a cu-local offset. Convert to section-global. */
        /*  It would be nice to put some code to check
            legality of the offset */
        /*  cc_debug_offset always has any DWP Package File
            offset included (when the cu_context created)
            so there is no extra work for DWP.

        /*  globalize the offset */
        offset += cu_context->cc_debug_offset;

        break;

    case DW_FORM_ref_addr:
        /*  This offset is defined to be debug_info global already, so
            use this value unaltered.

            Since a DWP package file is not relocated there
            is no way that this reference offset to an address in
            any other CU can be correct for a DWP Package File offset
            */
        break;

    default:
        _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
        return (DW_DLV_ERROR);
    }

    *ret_offset = (offset);
    return DW_DLV_OK;
}
Exemple #10
0
int
dwarf_formexprloc(Dwarf_Attribute attr,
    Dwarf_Unsigned * return_exprlen,
    Dwarf_Ptr  * block_ptr,
    Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
        return (DW_DLV_ERROR);
    }
    if (attr->ar_attribute_form == DW_FORM_exprloc ) {
        Dwarf_Die die = 0;
        Dwarf_Word leb_len = 0;
        Dwarf_Unsigned exprlen =
            (_dwarf_decode_u_leb128(attr->ar_debug_ptr, &leb_len));
        Dwarf_Small * addr = attr->ar_debug_ptr;
        /*  Is the block entirely in the section, or is
            there bug somewhere? */
        die = attr->ar_die;
        if (_dwarf_reference_outside_section(die,
            (Dwarf_Small *)addr, ((Dwarf_Small *)addr)+exprlen +leb_len)) {
            _dwarf_error(dbg, error,DW_DLE_ATTR_OUTSIDE_SECTION);
            return DW_DLV_ERROR;
        }
        *return_exprlen = exprlen;
        *block_ptr = addr + leb_len;
        return DW_DLV_OK;

    }
    _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD);
    return (DW_DLV_ERROR);
}
Exemple #11
0
/*  Convert an offset within the local CU into a section-relative
    debug_info offset. See dwarf_global_formref() and dwarf_formref()
    for additional information on conversion rules.
*/
int
dwarf_convert_to_global_offset(Dwarf_Attribute attr,
    Dwarf_Off offset, Dwarf_Off * ret_offset, Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;
  
    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) { 
        return res;
    } 

    switch (attr->ar_attribute_form) {
    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref8:
    case DW_FORM_ref_udata:
        /*  It would be nice to put some code to check 
            legality of the offset */
        /*  globalize the offset */
        offset += cu_context->cc_debug_offset;
        break;

    case DW_FORM_ref_addr:
        /*  This offset is defined to be debug_info global already, so
            use this value unaltered. */
        break;

    default:
        _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
        return (DW_DLV_ERROR);
    }

    *ret_offset = (offset);
    return DW_DLV_OK;
}
Exemple #12
0
/*  If the form is DW_FORM_constx and the .debug_addr section
    is missing, this returns DW_DLV_ERROR and the error number
    in the Dwarf_Error is  DW_DLE_MISSING_NEEDED_DEBUG_ADDR_SECTION.
    When that arises, a consumer should call
    dwarf_get_debug_addr_index() and use that on the appropriate
    .debug_addr section in the executable or another object. */
int
dwarf_formudata(Dwarf_Attribute attr,
    Dwarf_Unsigned * return_uval, Dwarf_Error * error)
{
    Dwarf_Unsigned ret_value = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    switch (attr->ar_attribute_form) {

    case DW_FORM_data1:
        READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Small));
        *return_uval = ret_value;
        return DW_DLV_OK;

    /*  READ_UNALIGNED does the right thing as it reads
        the right number bits and generates host order.
        So we can just assign to *return_uval. */
    case DW_FORM_data2:{
        READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Half));
        *return_uval = ret_value;
        return DW_DLV_OK;
        }

    case DW_FORM_data4:{
        READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
            attr->ar_debug_ptr,
            sizeof(Dwarf_ufixed));
        *return_uval = ret_value;
        return DW_DLV_OK;
        }

    case DW_FORM_data8:{
        READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
            attr->ar_debug_ptr,
            sizeof(Dwarf_Unsigned));
        *return_uval = ret_value;
        return DW_DLV_OK;
        }
        break;
    /* real udata */
    case DW_FORM_udata:
        ret_value =
            (_dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL));
        *return_uval = ret_value;
        return DW_DLV_OK;


        /*  IRIX bug 583450. We do not allow reading sdata from a udata
            value. Caller can retry, calling sdata */


    default:
        break;
    }
    _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
    return (DW_DLV_ERROR);
}
Exemple #13
0
/* Contrary to long standing documentation,
   The string pointer returned thru return_str must
   never have dwarf_dealloc() applied to it.
   Documentation fixed July 2005.
*/
int
dwarf_formstring(Dwarf_Attribute attr,
    char **return_str, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned offset = 0;
    int res = DW_DLV_ERROR;

    res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) { 
        return res;
    } 
    if (attr->ar_attribute_form == DW_FORM_string) {

        void *begin = attr->ar_debug_ptr;

        if (0 == dbg->de_assume_string_in_bounds) {
            /* Check that string lies within current cu in .debug_info. 
            */
            void *end = dbg->de_debug_info.dss_data +
                cu_context->cc_debug_offset +
                cu_context->cc_length + cu_context->cc_length_size +
                cu_context->cc_extension_size;
            if (0 == _dwarf_string_valid(begin, end)) {
                _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
                return (DW_DLV_ERROR);
            }
        }
        *return_str = (char *) (begin);
        return DW_DLV_OK;
    }

    if (attr->ar_attribute_form == DW_FORM_strp) {
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr,
            cu_context->cc_length_size);

        res = _dwarf_load_section(dbg, &dbg->de_debug_str,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        if (0 == dbg->de_assume_string_in_bounds) {
            /* Check that string lies within current cu in .debug_info. 
            */
            void *end = dbg->de_debug_str.dss_data + 
                dbg->de_debug_str.dss_size;
            void*begin = dbg->de_debug_str.dss_data + offset;
            if (0 == _dwarf_string_valid(begin, end)) {
                _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD);
                return (DW_DLV_ERROR);
            }
        }

        /*  Ensure the offset lies within the .debug_str */
        if (offset >= dbg->de_debug_str.dss_size) {
            _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }

        *return_str = (char *) (dbg->de_debug_str.dss_data + offset);
        return DW_DLV_OK;
    }

    _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
    return (DW_DLV_ERROR);
}
Exemple #14
0
int
dwarf_global_formref(Dwarf_Attribute attr,
    Dwarf_Off * ret_offset, Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned offset = 0;
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Half context_version = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    context_version = cu_context->cc_version_stamp;
    switch (attr->ar_attribute_form) {

    case DW_FORM_ref1:
        offset = *(Dwarf_Small *) attr->ar_debug_ptr;
        goto fixoffset;

    case DW_FORM_ref2:
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Half));
        goto fixoffset;

    case DW_FORM_ref4:
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
        goto fixoffset;

    case DW_FORM_ref8:
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
        goto fixoffset;

    case DW_FORM_ref_udata:
        {
        offset = _dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL);

        fixoffset: /* we have a local offset, make it global */

        /* check legality of offset */
        if (offset >= cu_context->cc_length +
            cu_context->cc_length_size +
            cu_context->cc_extension_size) {
            _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }

        /* globalize the offset */
        offset += cu_context->cc_debug_offset;
        }
        break;

    /*  The DWARF2 document did not make clear that
        DW_FORM_data4( and 8) were references with
        global offsets to some section.
        That was first clearly documented in DWARF3.
        In DWARF4 these two forms are no longer references. */
    case DW_FORM_data4:
        if (context_version == DW_CU_VERSION4) {
            _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM);
            return (DW_DLV_ERROR);
        }
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
        /* The offset is global. */
        break;
    case DW_FORM_data8:
        if (context_version == DW_CU_VERSION4) {
            _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM);
            return (DW_DLV_ERROR);
        }
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
        /* The offset is global. */
        break;
    case DW_FORM_ref_addr:
        {
            /*  In Dwarf V2 DW_FORM_ref_addr was defined
                as address-size even though it is a .debug_info
                offset.  Fixed in Dwarf V3 to be offset-size.
                */
            unsigned length_size = 0;
            if (context_version == 2) {
                length_size = cu_context->cc_address_size;
            } else {
                length_size = cu_context->cc_length_size;
            }
            if (length_size == 4) {
                READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
                    attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
            } else if (length_size == 8) {
                READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
                    attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
            } else {
                _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD);
                return (DW_DLV_ERROR);
            }
        }
        break;
    case DW_FORM_sec_offset:
    case DW_FORM_GNU_ref_alt:  /* 2013 GNU extension */
    case DW_FORM_GNU_strp_alt:  /* 2013 GNU extension */
        {
            /*  DW_FORM_sec_offset first exists in DWARF4.*/
            /*  It is up to the caller to know what the offset
                of DW_FORM_sec_offset refers to,
                the offset is not going to refer to .debug_info! */
            unsigned length_size = cu_context->cc_length_size;
            if (length_size == 4) {
                READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
                    attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
            } else if (length_size == 8) {
                READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
                    attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
            } else {
                _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD);
                return (DW_DLV_ERROR);
            }
        }
        break;
    case DW_FORM_ref_sig8: /* FIXME */
        /*  We cannot handle this yet.
            The reference is to .debug_types, and
            this function only returns an offset in
            .debug_info at this point. */
        _dwarf_error(dbg, error, DW_DLE_REF_SIG8_NOT_HANDLED);
        return (DW_DLV_ERROR);
    default:
        _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
        return (DW_DLV_ERROR);
    }

    /*  We do not know what section the offset refers to, so
        we have no way to check it for correctness. */
    *ret_offset = offset;
    return DW_DLV_OK;
}
Exemple #15
0
int
dwarf_formref(Dwarf_Attribute attr,
   Dwarf_Off * ret_offset,
   Dwarf_Error * error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned offset = 0;
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Unsigned maximumoffset = 0;
    int res = DW_DLV_ERROR;

    *ret_offset = 0;
    res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    switch (attr->ar_attribute_form) {

    case DW_FORM_ref1:
        offset = *(Dwarf_Small *) attr->ar_debug_ptr;
        break;

    case DW_FORM_ref2:
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Half));
        break;

    case DW_FORM_ref4:
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
        break;

    case DW_FORM_ref8:
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
        break;

    case DW_FORM_ref_udata:
        offset = _dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL);
        break;
    case DW_FORM_ref_sig8:
        /*  We cannot handle this here.
            The reference is to .debug_types
            not a .debug_info CU local offset. */
        _dwarf_error(dbg, error, DW_DLE_REF_SIG8_NOT_HANDLED);
        return (DW_DLV_ERROR);
    default:
        _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
        return (DW_DLV_ERROR);
    }

    /* Check that offset is within current cu portion of .debug_info. */

    maximumoffset = cu_context->cc_length +
        cu_context->cc_length_size +
        cu_context->cc_extension_size;
    if (offset >= maximumoffset) {
        /*  For the DW_TAG_compile_unit is legal to have the
            DW_AT_sibling attribute outside the current cu portion of
            .debug_info.
            In other words, sibling points to the end of the CU.
            It is used for precompiled headers.
            The valid condition will be: 'offset == maximumoffset'. */
        Dwarf_Half tag = 0;
        if (DW_DLV_OK != dwarf_tag(attr->ar_die,&tag,error)) {
            _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
            return (DW_DLV_ERROR);
        }

        if (DW_TAG_compile_unit != tag &&
            DW_AT_sibling != attr->ar_attribute &&
            offset > maximumoffset) {
            _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD);
            /* Return the incorrect offset for better error reporting */
            *ret_offset = (offset);
            return (DW_DLV_ERROR);
        }
    }
    *ret_offset = (offset);
    return DW_DLV_OK;
}
Exemple #16
0
/* Contrary to pre-2005 documentation,
   The string pointer returned thru return_str must
   never have dwarf_dealloc() applied to it.
   Documentation fixed July 2005.
*/
int
dwarf_formstring(Dwarf_Attribute attr,
    char **return_str, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned offset = 0;
    int res = DW_DLV_ERROR;
    Dwarf_Small *dataptr = 0;
    Dwarf_Small *infoptr = attr->ar_debug_ptr;
    res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    dataptr = cu_context->cc_is_info?
        dbg->de_debug_info.dss_data:
        dbg->de_debug_types.dss_data;
    if (attr->ar_attribute_form == DW_FORM_string) {

        void *begin = attr->ar_debug_ptr;

        if (0 == dbg->de_assume_string_in_bounds) {
            /* Check that string lies within current cu in .debug_info.
            */

            void *end = dataptr +
                cu_context->cc_debug_offset +
                cu_context->cc_length + cu_context->cc_length_size +
                cu_context->cc_extension_size;
            if (0 == _dwarf_string_valid(begin, end)) {
                _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
                return (DW_DLV_ERROR);
            }
        }
        *return_str = (char *) (begin);
        return DW_DLV_OK;
    }
    if (attr->ar_attribute_form == DW_FORM_GNU_strp_alt) {
        /* Unsure what this is really. FIXME */
        *return_str = (char *)"<DW_FORM_GNU_strp_alt not handled>";
        return DW_DLV_OK;
    }
    if (attr->ar_attribute_form == DW_FORM_GNU_str_index ||
        attr->ar_attribute_form == DW_FORM_strx) {
        Dwarf_Unsigned offsettostr= 0;
        res = _dwarf_extract_string_offset_via_str_offsets(dbg,
            infoptr,
            attr->ar_attribute,
            attr->ar_attribute_form,
            cu_context,
            &offsettostr,
            error);
        offset = offsettostr;
        /* FALL THRU */
    } else {
        if (attr->ar_attribute_form == DW_FORM_strp) {
            READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
                infoptr,
                cu_context->cc_length_size);
        }
    }
    if (attr->ar_attribute_form == DW_FORM_strp ||
        attr->ar_attribute_form == DW_FORM_GNU_str_index ||
        attr->ar_attribute_form == DW_FORM_strx) {
        /* The 'offset' into .debug_str is set. */
        res = _dwarf_load_section(dbg, &dbg->de_debug_str,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        if (offset >= dbg->de_debug_str.dss_size) {
            /*  Badly damaged DWARF here. */
            _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }
        if (0 == dbg->de_assume_string_in_bounds) {
            /* Check that string lies within its   .debug_str.  */
            void *end = dbg->de_debug_str.dss_data +
                dbg->de_debug_str.dss_size;
            void*begin = dbg->de_debug_str.dss_data + offset;
            if (0 == _dwarf_string_valid(begin, end)) {
                _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD);
                return (DW_DLV_ERROR);
            }
        }

        /*  Ensure the offset lies within the .debug_str */
        if (offset >= dbg->de_debug_str.dss_size) {
            _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }

        *return_str = (char *) (dbg->de_debug_str.dss_data + offset);
        return DW_DLV_OK;
    }

    _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
    return (DW_DLV_ERROR);
}
Exemple #17
0
int
dwarf_formsdata(Dwarf_Attribute attr,
    Dwarf_Signed * return_sval, Dwarf_Error * error)
{
    Dwarf_Signed ret_value = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_CU_Context cu_context = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    switch (attr->ar_attribute_form) {

    case DW_FORM_data1:
        *return_sval = (*(Dwarf_Sbyte *) attr->ar_debug_ptr);
        return DW_DLV_OK;

    /*  READ_UNALIGNED does not sign extend.
        So we have to use a cast to get the
        value sign extended in the right way for each case. */
    case DW_FORM_data2:{
        READ_UNALIGNED(dbg, ret_value, Dwarf_Signed,
            attr->ar_debug_ptr,
            sizeof(Dwarf_Shalf));
        *return_sval = (Dwarf_Shalf) ret_value;
        return DW_DLV_OK;

        }

    case DW_FORM_data4:{
        READ_UNALIGNED(dbg, ret_value, Dwarf_Signed,
            attr->ar_debug_ptr,
            sizeof(Dwarf_sfixed));
        *return_sval = (Dwarf_sfixed) ret_value;
        return DW_DLV_OK;
        }

    case DW_FORM_data8:{
        READ_UNALIGNED(dbg, ret_value, Dwarf_Signed,
            attr->ar_debug_ptr,
            sizeof(Dwarf_Signed));
        *return_sval = (Dwarf_Signed) ret_value;
        return DW_DLV_OK;
        }

    case DW_FORM_sdata:
        ret_value =
            (_dwarf_decode_s_leb128(attr->ar_debug_ptr, NULL));
        *return_sval = ret_value;
        return DW_DLV_OK;

        /* IRIX bug 583450. We do not allow reading sdata from a udata
            value. Caller can retry, calling udata */

    default:
        break;
    }
    _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
    return DW_DLV_ERROR;
}
Exemple #18
0
int
dwarf_formblock(Dwarf_Attribute attr,
    Dwarf_Block ** return_block, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned length = 0;
    Dwarf_Small *data = 0;
    Dwarf_Word leb128_length = 0;
    Dwarf_Block *ret_block = 0;
    Dwarf_Small *dataptr = 0;

    int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    switch (attr->ar_attribute_form) {

    case DW_FORM_block1:
        length = *(Dwarf_Small *) attr->ar_debug_ptr;
        data = attr->ar_debug_ptr + sizeof(Dwarf_Small);
        break;

    case DW_FORM_block2:
        READ_UNALIGNED(dbg, length, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_Half));
        data = attr->ar_debug_ptr + sizeof(Dwarf_Half);
        break;

    case DW_FORM_block4:
        READ_UNALIGNED(dbg, length, Dwarf_Unsigned,
            attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
        data = attr->ar_debug_ptr + sizeof(Dwarf_ufixed);
        break;

    case DW_FORM_block:
        length = _dwarf_decode_u_leb128(attr->ar_debug_ptr,
            &leb128_length);
        data = attr->ar_debug_ptr + leb128_length;
        break;

    default:
        _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD);
        return (DW_DLV_ERROR);
    }

    /* Check that block lies within current cu in .debug_info. */
    dataptr = cu_context->cc_is_info? dbg->de_debug_info.dss_data:
        dbg->de_debug_types.dss_data;

    if (attr->ar_debug_ptr + length >=
        dataptr + cu_context->cc_debug_offset +
        cu_context->cc_length + cu_context->cc_length_size +
        cu_context->cc_extension_size) {
        _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
        return (DW_DLV_ERROR);
    }

    ret_block = (Dwarf_Block *) _dwarf_get_alloc(dbg, DW_DLA_BLOCK, 1);
    if (ret_block == NULL) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }

    ret_block->bl_len = length;
    ret_block->bl_data = (Dwarf_Ptr) data;
    ret_block->bl_from_loclist = 0;
    ret_block->bl_section_offset = data - dataptr;


    *return_block = ret_block;
    return (DW_DLV_OK);
}
Exemple #19
0
/* Contrary to pre-2005 documentation,
   The string pointer returned thru return_str must
   never have dwarf_dealloc() applied to it.
   Documentation fixed July 2005.
*/
int
dwarf_formstring(Dwarf_Attribute attr,
    char **return_str, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned offset = 0;
    int res = DW_DLV_ERROR;
    Dwarf_Small *secdataptr = 0;
    Dwarf_Small *secend = 0;
    Dwarf_Unsigned secdatalen = 0;
    Dwarf_Small *infoptr = attr->ar_debug_ptr;
    res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    if (cu_context->cc_is_info) {
        secdataptr = (Dwarf_Small *)dbg->de_debug_info.dss_data;
        secdatalen = dbg->de_debug_info.dss_size;
    } else {
        secdataptr = (Dwarf_Small *)dbg->de_debug_types.dss_data;
        secdatalen = dbg->de_debug_types.dss_size;
    }
    switch(attr->ar_attribute_form) {
    case DW_FORM_string: {
        Dwarf_Small *begin = attr->ar_debug_ptr;
        Dwarf_Small *contextend = secdataptr +
            cu_context->cc_debug_offset +
            cu_context->cc_length +
            cu_context->cc_length_size +
            cu_context->cc_extension_size;
        secend = secdataptr + secdatalen;
        if (contextend < secend) {
            secend = contextend;
        }

        res= _dwarf_check_string_valid(dbg,secdataptr,begin, secend,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        *return_str = (char *) (begin);
        return DW_DLV_OK;
    }
    case DW_FORM_GNU_strp_alt:
    case DW_FORM_strp_sup:  {
        Dwarf_Error alterr = 0;
        /*  See dwarfstd.org issue 120604.1
            This is the offset in the .debug_str section
            of another object file.
            The 'tied' file notion should apply.
            It is not clear whether both a supplementary
            and a split object might be needed at the same time
            (hence two 'tied' files simultaneously). */
        Dwarf_Off soffset = 0;

        res = dwarf_global_formref(attr, &soffset,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        res = _dwarf_get_string_from_tied(dbg, soffset,
            return_str, &alterr);
        if (res == DW_DLV_ERROR) {
            if (dwarf_errno(alterr) == DW_DLE_NO_TIED_FILE_AVAILABLE) {
                dwarf_dealloc(dbg,alterr,DW_DLA_ERROR);
                if( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) {
                    *return_str =
                        (char *)"<DW_FORM_GNU_strp_alt-no-tied-file>";
                } else {
                    *return_str =
                        (char *)"<DW_FORM_strp_sup-no-tied-file>";
                }
                return DW_DLV_OK;
            }
            if (error) {
                *error = alterr;
            }
            return res;
        }
        if (res == DW_DLV_NO_ENTRY) {
            if( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) {
                *return_str =
                    (char *)"<DW_FORM_GNU_strp_alt-no-tied-file>";
            }else {
                *return_str =
                    (char *)"<DW_FORM_strp_sup-no-tied-file>";
            }
        }
        return res;
    }
    case DW_FORM_GNU_str_index:
    case DW_FORM_strx: {
        Dwarf_Unsigned offsettostr= 0;
        res = _dwarf_extract_string_offset_via_str_offsets(dbg,
            infoptr,
            attr->ar_attribute,
            attr->ar_attribute_form,
            cu_context,
            &offsettostr,
            error);
        if (res != DW_DLV_OK) {
            return res;
        }
        offset = offsettostr;
        break;
    }
    case DW_FORM_strp:
    case DW_FORM_line_strp:{
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            infoptr,
            cu_context->cc_length_size);
        break;
    }
    default:
        _dwarf_error(dbg, error, DW_DLE_STRING_FORM_IMPROPER);
        return DW_DLV_ERROR;
    }
    /*  Now we have offset so read the string from
        debug_str or debug_line_str. */
    res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
        attr->ar_attribute_form,
        offset,
        return_str,
        error);
    return res;
}