Пример #1
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;
}
Пример #2
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);
}
/*  Here a DW_DLV_NO_ENTRY return means the macro operator
    is not a def/undef operator. */
int
dwarf_get_macro_defundef(Dwarf_Macro_Context macro_context,
    Dwarf_Unsigned op_number,
    Dwarf_Unsigned * line_number,
    Dwarf_Unsigned * index,
    Dwarf_Unsigned * offset,
    Dwarf_Half     * forms_count,
    const char     ** macro_string,
    Dwarf_Error *error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Small *mdata = 0;
    int res = 0;
    Dwarf_Small *startptr = 0;
    Dwarf_Small *endptr = 0;
    Dwarf_Half lformscount = 0;
    struct Dwarf_Macro_Operator_s *curop = 0;
    unsigned macop = 0;

    if (!macro_context || macro_context->mc_sentinel != 0xada) {
        if(macro_context) {
            dbg = macro_context->mc_dbg;
        }
        _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
        return DW_DLV_ERROR;
    }
    dbg = macro_context->mc_dbg;
    if (op_number >= macro_context->mc_macro_ops_count) {
        _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX);
        return DW_DLV_ERROR;
    }
    curop = macro_context->mc_ops + op_number;
    macop = curop->mo_opcode;
    startptr = macro_context->mc_macro_header;
    endptr = startptr + macro_context->mc_total_length;
    mdata = curop->mo_data;
    lformscount = curop->mo_form->mf_formcount;
    if (lformscount != 2) {
        /*_dwarf_error(dbg, error,DW_DLE_MACRO_OPCODE_FORM_BAD);*/
        return DW_DLV_NO_ENTRY;
    }
    switch(macop){
    case DW_MACRO_define:
    case DW_MACRO_undef: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        const char * content = 0;

        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;
        content = (const char *)mdata;
        res = _dwarf_check_string_valid(dbg,
            startptr,mdata, endptr, error);
        if(res != DW_DLV_OK) {
            return res;
        }
        *line_number = linenum;
        *index = 0;
        *offset = 0;
        *forms_count = lformscount;
        *macro_string = content;
        }
        return DW_DLV_OK;
    case DW_MACRO_define_strp:
    case DW_MACRO_undef_strp: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Unsigned stringoffset = 0;
        Dwarf_Small form1 =  curop->mo_form->mf_formbytes[1];
        char * localstr = 0;


        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;

        READ_UNALIGNED(dbg,stringoffset,Dwarf_Unsigned,
            mdata,macro_context->mc_offset_size);
        mdata += macro_context->mc_offset_size;

        res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
            form1,
            stringoffset,
            &localstr,
            error);
        *index = 0;
        *line_number = linenum;
        *offset = stringoffset;
        *forms_count = lformscount;
        if (res == DW_DLV_ERROR) {
            return res;
            *macro_string = "<Error: getting local .debug_str>";
        } else if (res == DW_DLV_NO_ENTRY) {
            *macro_string = "<Error: NO_ENTRY on .debug_string (strp)>";
        } else {
            *macro_string = (const char *)localstr;
        }
        }
        return DW_DLV_OK;
    case DW_MACRO_define_strx:
    case DW_MACRO_undef_strx: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Unsigned stringindex = 0;
        Dwarf_Unsigned offsettostr= 0;
        int res = 0;
        Dwarf_Small form1 =  curop->mo_form->mf_formbytes[1];

        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;

        *line_number = linenum;
        stringindex = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        /* leave mdata uchanged for call below */


        *index = stringindex;
        *forms_count = lformscount;

        /* FIXME */
        /* Redoes the index-getting. Gets offset. */
        res = _dwarf_extract_string_offset_via_str_offsets(dbg,
            mdata,
            DW_AT_macros, /*arbitrary, unused by called routine. */
            form1,
            macro_context->mc_cu_context,
            &offsettostr,
            error);
        if (res  == DW_DLV_ERROR) {
            return res;
        }
        if (res == DW_DLV_OK) {
            *index = stringindex;
            *offset = offsettostr;
            char *localstr = 0;
            res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
                form1,
                offsettostr,
                &localstr,
                error);
            if(res == DW_DLV_ERROR) {
                return res;
            } else if (res == DW_DLV_NO_ENTRY){
                *macro_string = "<:No string available>";
            } else {
                *macro_string = (const char *)localstr;
                /* All is ok. */
            }
        } else {
            *index = stringindex;
            *offset = 0;
            *macro_string = "<.debug_str_offsets not available>";
        }
        }
        return DW_DLV_OK;
    case DW_MACRO_define_sup:
    case DW_MACRO_undef_sup: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Unsigned supoffset = 0;
        char *localstring = 0;
        int res = 0;

        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;

        READ_UNALIGNED(dbg,supoffset,Dwarf_Unsigned,
            mdata,macro_context->mc_offset_size);
        mdata += macro_context->mc_offset_size;
        *line_number = linenum;
        *index = 0;
        *offset = supoffset;
        *forms_count = lformscount;
        res = _dwarf_get_string_from_tied(dbg, supoffset,
            &localstring, error);
        if (res != DW_DLV_OK) {
            if (res == DW_DLV_ERROR) {
                if(dwarf_errno(*error) == DW_DLE_NO_TIED_FILE_AVAILABLE) {
                    *macro_string =
                        (char *)"<DW_FORM_str_sup-no-tied_file>";
                } else {
                    *macro_string =
                        (char *)"<Error: DW_FORM_str_sup-got-error>";
                }
                dwarf_dealloc(dbg,*error,DW_DLA_ERROR);
            } else {
                *macro_string = "<DW_FORM_str_sup-no-entry>";
            }
        } else {
            *macro_string = (const char *)localstring;
        }
        return DW_DLV_OK;
        }
    }
    return DW_DLV_NO_ENTRY;
}