Beispiel #1
0
int
_dwarf_get_string_from_tied(Dwarf_Debug dbg,
    Dwarf_Unsigned offset,
    char **return_str,
    Dwarf_Error*error)
{
    Dwarf_Debug tieddbg = 0;
    Dwarf_Small *secend = 0;
    Dwarf_Small *secbegin = 0;
    Dwarf_Small *strbegin = 0;
    int res = DW_DLV_ERROR;
    Dwarf_Error localerror = 0;

    /* Attach errors to dbg, not tieddbg. */
    tieddbg = dbg->de_tied_data.td_tied_object;
    if (!tieddbg) {
        _dwarf_error(dbg, error, DW_DLE_NO_TIED_FILE_AVAILABLE);
        return  DW_DLV_ERROR;
    }
    /* The 'offset' into .debug_str is set. */
    res = _dwarf_load_section(tieddbg, &tieddbg->de_debug_str,&localerror);
    if (res == DW_DLV_ERROR) {
        Dwarf_Unsigned lerrno = dwarf_errno(localerror);
        dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR);
        _dwarf_error(dbg,error,lerrno);
        return res;
    } else if (res == DW_DLV_NO_ENTRY) {
        return res;
    }
    if (offset >= tieddbg->de_debug_str.dss_size) {
        /*  Badly damaged DWARF here. */
        _dwarf_error(dbg, error,  DW_DLE_NO_TIED_STRING_AVAILABLE);
        return (DW_DLV_ERROR);
    }
    secbegin = tieddbg->de_debug_str.dss_data;
    strbegin= tieddbg->de_debug_str.dss_data + offset;
    secend = tieddbg->de_debug_str.dss_data +
        tieddbg->de_debug_str.dss_size;

    /*  Ensure the offset lies within the .debug_str */
    if (offset >= tieddbg->de_debug_str.dss_size) {
        _dwarf_error(dbg, error,  DW_DLE_NO_TIED_STRING_AVAILABLE);
        return (DW_DLV_ERROR);
    }
    res= _dwarf_check_string_valid(tieddbg,secbegin,strbegin, secend,
        &localerror);
    if (res == DW_DLV_ERROR) {
        Dwarf_Unsigned lerrno = dwarf_errno(localerror);
        dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR);
        _dwarf_error(dbg,error,lerrno);
        return res;
    } else if (res == DW_DLV_NO_ENTRY) {
        return res;
    }
    *return_str = (char *) (tieddbg->de_debug_str.dss_data + offset);
    return DW_DLV_OK;
}
Beispiel #2
0
int
_dwarf_extract_local_debug_str_string_given_offset(Dwarf_Debug dbg,
    unsigned attrform,
    Dwarf_Unsigned offset,
    char ** return_str,
    Dwarf_Error * error)
{
    if (attrform == DW_FORM_strp ||
        attrform == DW_FORM_line_strp ||
        attrform == DW_FORM_GNU_str_index ||
        attrform == DW_FORM_strx) {
        /*  The 'offset' into .debug_str or .debug_line_str is given,
            here we turn that into a pointer. */
        Dwarf_Small   *secend = 0;
        Dwarf_Small   *secbegin = 0;
        Dwarf_Small   *strbegin = 0;
        Dwarf_Unsigned secsize = 0;
        int errcode = 0;
        int res = 0;

        if(attrform == DW_FORM_line_strp) {
            res = _dwarf_load_section(dbg, &dbg->de_debug_line_str,error);
            if (res != DW_DLV_OK) {
                return res;
            }
            errcode = DW_DLE_STRP_OFFSET_BAD;
            secsize = dbg->de_debug_line_str.dss_size;
            secbegin = dbg->de_debug_line_str.dss_data;
            strbegin= dbg->de_debug_line_str.dss_data + offset;
        } else {
            res = _dwarf_load_section(dbg, &dbg->de_debug_str,error);
            if (res != DW_DLV_OK) {
                return res;
            }
            errcode = DW_DLE_STRP_OFFSET_BAD;
            secsize = dbg->de_debug_str.dss_size;
            secbegin = dbg->de_debug_str.dss_data;
            strbegin= dbg->de_debug_str.dss_data + offset;
            secend = dbg->de_debug_str.dss_data + secsize;
        }
        if (offset >= secsize) {
            /*  Badly damaged DWARF here. */
            _dwarf_error(dbg, error, errcode);
            return (DW_DLV_ERROR);
        }
        res= _dwarf_check_string_valid(dbg,secbegin,strbegin, secend,error);
        if (res != DW_DLV_OK) {
            return res;
        }

        *return_str = (char *)strbegin;
        return DW_DLV_OK;
    }
    _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
    return (DW_DLV_ERROR);
}
Beispiel #3
0
int
dwarf_get_macro_details(Dwarf_Debug dbg,
                        Dwarf_Off macro_offset,
                        Dwarf_Unsigned maximum_count,
                        Dwarf_Signed * entry_count,
                        Dwarf_Macro_Details ** details,
                        Dwarf_Error * error)
{
    Dwarf_Small *macro_base = 0;
    Dwarf_Small *macro_end = 0;
    Dwarf_Small *pnext = 0;
    Dwarf_Unsigned endloc = 0;
    unsigned char uc = 0;
    unsigned long depth = 0;
    /* By section 6.3.2 Dwarf3 draft 8/9,
    the base file should appear as
    DW_MACINFO_start_file. See
    http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html
    on "[Bug debug/20253] New: [3.4/4.0 regression]:
    Macro debug info broken due to lexer change" for how
    gcc is broken in some versions. We no longer use
    depth as a stopping point, it's not needed as a
    stopping point anyway.  */
    int res = 0;
    /* count space used by strings */
    unsigned long str_space = 0;
    int done = 0;
    unsigned long space_needed = 0;
    unsigned long string_offset = 0;
    Dwarf_Small *return_data = 0;
    Dwarf_Small *pdata = 0;
    unsigned long final_count = 0;
    Dwarf_Signed fileindex = -1;
    Dwarf_Small *latest_str_loc = 0;
    struct macro_stack_s msdata;

    unsigned long count = 0;
    unsigned long max_count = (unsigned long) maximum_count;

    _dwarf_reset_index_macro_stack(&msdata);
    if (dbg == NULL) {
        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
        free_macro_stack(dbg,&msdata);
        return (DW_DLV_ERROR);
    }

    res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error);
    if (res != DW_DLV_OK) {
        free_macro_stack(dbg,&msdata);
        return res;
    }
    if (!dbg->de_debug_abbrev.dss_size) {
        free_macro_stack(dbg,&msdata);
        return (DW_DLV_NO_ENTRY);
    }

    macro_base = dbg->de_debug_macinfo.dss_data;
    if (macro_base == NULL) {
        free_macro_stack(dbg,&msdata);
        return (DW_DLV_NO_ENTRY);
    }
    if (macro_offset >= dbg->de_debug_macinfo.dss_size) {
        free_macro_stack(dbg,&msdata);
        return (DW_DLV_NO_ENTRY);
    }
    macro_end = macro_base + dbg->de_debug_macinfo.dss_size;
    /*   FIXME debugfission is NOT handled here.  */

    pnext = macro_base + macro_offset;
    if (maximum_count == 0) {
        max_count = ULONG_MAX;
    }


    /* how many entries and how much space will they take? */

    endloc = (pnext - macro_base);
    if (endloc >= dbg->de_debug_macinfo.dss_size) {
        if (endloc == dbg->de_debug_macinfo.dss_size) {
            /* normal: found last entry */
            free_macro_stack(dbg,&msdata);
            return DW_DLV_NO_ENTRY;
        }
        _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
        free_macro_stack(dbg,&msdata);
        return (DW_DLV_ERROR);
    }
    for (count = 0; !done && count < max_count; ++count) {
        unsigned long slen = 0;

        /* Set but not used */
        UNUSEDARG Dwarf_Unsigned utemp = 0;

        uc = *pnext;
        ++pnext;                /* get past the type code */
        switch (uc) {
        case DW_MACINFO_define:
        case DW_MACINFO_undef:
        /* line, string */
        case DW_MACINFO_vendor_ext:
            /* number, string */
            DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error,
                                   macro_end);
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            res = _dwarf_check_string_valid(dbg,
                                            macro_base,pnext,macro_end,error);
            if (res != DW_DLV_OK) {
                return res;
            }
            slen = strlen((char *) pnext) + 1;
            pnext += slen;
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            str_space += slen;
            break;
        case DW_MACINFO_start_file:
            /* line, file index */
            DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error,
                                   macro_end);
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error,
                                   macro_end);
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            ++depth;
            break;

        case DW_MACINFO_end_file:
            if (--depth == 0) {
                /*  done = 1; no, do not stop here, at least one gcc had
                    the wrong depth settings in the gcc 3.4 timeframe. */
            }
            /* no string or number here */
            break;
        case 0:
            /* end of cu's entries */
            done = 1;
            break;
        default:
            free_macro_stack(dbg,&msdata);
            _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
            return (DW_DLV_ERROR);
            /* bogus macinfo! */
        }

        endloc = (pnext - macro_base);
        if (endloc == dbg->de_debug_macinfo.dss_size) {
            done = 1;
        } else if (endloc > dbg->de_debug_macinfo.dss_size) {
            _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
            free_macro_stack(dbg,&msdata);
            return (DW_DLV_ERROR);
        }
    }
    if (count == 0) {
        free_macro_stack(dbg,&msdata);
        _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR);
        return (DW_DLV_ERROR);
    }

    /*  We have 'count' array entries to allocate and str_space bytes of
        string space to provide for. */

    string_offset = count * sizeof(Dwarf_Macro_Details);

    /* extra 2 not really needed */
    space_needed = string_offset + str_space + 2;
    return_data = pdata =
                      (Dwarf_Small *)_dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed);
    latest_str_loc = pdata + string_offset;
    if (pdata == 0) {
        free_macro_stack(dbg,&msdata);
        _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
        return (DW_DLV_ERROR);
    }
    pnext = macro_base + macro_offset;

    done = 0;

    /* A series ends with a type code of 0. */

    for (final_count = 0; !done && final_count < count; ++final_count) {
        unsigned long slen = 0;
        Dwarf_Unsigned v1 = 0;
        Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
                                    (final_count * sizeof (Dwarf_Macro_Details)));

        endloc = (pnext - macro_base);
        if (endloc > dbg->de_debug_macinfo.dss_size) {
            free_macro_stack(dbg,&msdata);
            _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
            return (DW_DLV_ERROR);
        }
        uc = *pnext;
        pdmd->dmd_offset = (pnext - macro_base);
        pdmd->dmd_type = uc;
        pdmd->dmd_fileindex = fileindex;
        pdmd->dmd_lineno = 0;
        pdmd->dmd_macro = 0;
        ++pnext;                /* get past the type code */
        switch (uc) {
        case DW_MACINFO_define:
        case DW_MACINFO_undef:
        /* line, string */
        case DW_MACINFO_vendor_ext:
            /* number, string */
            DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error,
                                   macro_end);
            pdmd->dmd_lineno = v1;

            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            res = _dwarf_check_string_valid(dbg,
                                            macro_base,pnext,macro_end,error);
            if (res != DW_DLV_OK) {
                return res;
            }
            slen = strlen((char *) pnext) + 1;
            strcpy((char *) latest_str_loc, (char *) pnext);
            pdmd->dmd_macro = (char *) latest_str_loc;
            latest_str_loc += slen;
            pnext += slen;
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            break;
        case DW_MACINFO_start_file:
            /* Line, file index */
            DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error,
                                   macro_end);
            pdmd->dmd_lineno = v1;
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error,
                                   macro_end);
            pdmd->dmd_fileindex = v1;
            (void) _dwarf_macro_stack_push_index(dbg, fileindex,
                                                 &msdata);
            /*  We ignore the error, we just let fileindex ** be -1 when
                we pop this one. */
            fileindex = v1;
            if (((Dwarf_Unsigned)(pnext - macro_base)) >=
                    dbg->de_debug_macinfo.dss_size) {
                free_macro_stack(dbg,&msdata);
                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
                _dwarf_error(dbg, error,
                             DW_DLE_DEBUG_MACRO_INCONSISTENT);
                return (DW_DLV_ERROR);
            }
            break;

        case DW_MACINFO_end_file:
            fileindex = _dwarf_macro_stack_pop_index(&msdata);
            break;              /* no string or number here */
        case 0:
            /* Type code of 0 means the end of cu's entries. */
            done = 1;
            break;
        default:
            /* Bogus macinfo! */
            dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
            free_macro_stack(dbg,&msdata);
            _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
            return (DW_DLV_ERROR);
        }
    }
    *entry_count = count;
    *details = (Dwarf_Macro_Details *) return_data;
    free_macro_stack(dbg,&msdata);
    return DW_DLV_OK;
}
Beispiel #4
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;
}
/*  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;
}
Beispiel #6
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;
}