コード例 #1
0
ファイル: dwarf_loc2.c プロジェクト: jrfonseca/drmingw
/* An interface giving us no cu context! */
int
dwarf_loclist_from_expr_c(Dwarf_Debug dbg,
    Dwarf_Ptr expression_in,
    Dwarf_Unsigned expression_length,
    Dwarf_Half address_size,
    Dwarf_Half offset_size,
    Dwarf_Small dwarf_version,
    Dwarf_Loc_Head_c *loc_head,
    Dwarf_Unsigned * listlen,
    Dwarf_Error * error)
{
    /* Dwarf_Block that describes a single location expression. */
    Dwarf_Block_c loc_block;
    Dwarf_Loc_Head_c llhead = 0;
    Dwarf_Locdesc_c llbuf = 0;
    int local_listlen = 1;
    Dwarf_Addr lowpc = 0;
    Dwarf_Addr highpc = MAX_ADDR;
    Dwarf_Small version_stamp = dwarf_version;
    int res = 0;

    llhead = (Dwarf_Loc_Head_c)_dwarf_get_alloc(dbg,
        DW_DLA_LOC_HEAD_C, 1);
    if (!llhead) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }
    memset(&loc_block,0,sizeof(loc_block));
    loc_block.bl_len = expression_length;
    loc_block.bl_data = expression_in;
    loc_block.bl_from_loclist = 0; /* Not from loclist. */
    loc_block.bl_section_offset = 0; /* Fake. Not meaningful. */
    loc_block.bl_locdesc_offset = 0; /* Fake. Not meaningful. */
    llbuf = (Dwarf_Locdesc_c)
        _dwarf_get_alloc(dbg, DW_DLA_LOCDESC_C, local_listlen);
    if (!llbuf) {
        dwarf_loc_head_c_dealloc(llhead);
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }
    llhead->ll_locdesc = llbuf;
    llhead->ll_locdesc_count = local_listlen;
    llhead->ll_from_loclist = 0;
    llhead->ll_context = 0; /* Not available! */
    llhead->ll_dbg = dbg;

    /* An empty location description (block length 0) means the code
    generator emitted no variable, the variable was not generated,
    it was unused or perhaps never tested after being set. Dwarf2,
    section 2.4.1 In other words, it is not an error, and we don't
    test for block length 0 specially here.  */

    res = _dwarf_get_locdesc_c(dbg,
        0,
        llhead,
        &loc_block,
        address_size,
        offset_size,
        version_stamp,
        lowpc,
        highpc,
        error);
    if (res != DW_DLV_OK) {
        /* low level error already set: let it be passed back */
        dwarf_loc_head_c_dealloc(llhead);
        return (DW_DLV_ERROR);
    }
    *loc_head = llhead;
    *listlen = local_listlen;
    return (DW_DLV_OK);
}
コード例 #2
0
ファイル: rdwarf.c プロジェクト: kubo/rdwarf
static VALUE rd_attr_loc_list(VALUE self)
{
    rd_attr_t *attr = GetAttr(self);
    Dwarf_Error err;
    Dwarf_Loc_Head_c loc_head;
    Dwarf_Unsigned count;
    VALUE lhead;
    Dwarf_Unsigned idx;

    chkerr1(dwarf_get_loclist_c(attr->attr, &loc_head, &count, &err), &err, self);
    lhead = rb_ary_new_capa(count);
    for (idx = 0; idx < count; idx++) {
        Dwarf_Small lle;
        Dwarf_Addr lowpc;
        Dwarf_Addr hipc;
        Dwarf_Unsigned loclist_count;
        Dwarf_Locdesc_c locentry;
        Dwarf_Small source;
        Dwarf_Unsigned expression_offset;
        Dwarf_Unsigned locdesc_offset;
        ID id_lle;
        ID id_lowpc;
        ID id_hipc;
        ID id_source;
        ID id_expression_offset;
        ID id_locdesc_offset;
        VALUE llist;
        int idx2;

        CONST_ID(id_lle, "@lle");
        CONST_ID(id_lowpc, "@lowpc");
        CONST_ID(id_hipc, "@hipc");
        CONST_ID(id_source, "@source");
        CONST_ID(id_expression_offset, "@expression_offset");
        CONST_ID(id_locdesc_offset, "@locdesc_offset");

        chkerr1(dwarf_get_locdesc_entry_c(loc_head, idx, &lle, &lowpc, &hipc,
                                          &loclist_count, &locentry, &source,
                                          &expression_offset, &locdesc_offset, &err),
                &err, self);
        llist = rb_class_new_instance(0, NULL, rd_cLocList);
        rb_ivar_set(llist, id_lle, rb_hash_aref(rdwarf_lle2name, INT2FIX(lle)));
        rb_ivar_set(llist, id_lowpc, ULL2NUM(lowpc));
        rb_ivar_set(llist, id_hipc, ULL2NUM(hipc));
        rb_ivar_set(llist, id_source, INT2FIX(source));
        rb_ivar_set(llist, id_expression_offset, ULL2NUM(expression_offset));
        rb_ivar_set(llist, id_locdesc_offset, ULL2NUM(locdesc_offset));
        for (idx2 = 0; idx2 < loclist_count; idx2++) {
            Dwarf_Small atom;
            Dwarf_Unsigned operand1;
            Dwarf_Unsigned operand2;
            Dwarf_Unsigned operand3;
            Dwarf_Unsigned offset_for_branch;
            ID id_atom;
            ID id_operand1;
            ID id_operand2;
            ID id_operand3;
            ID id_offset_for_branch;
            VALUE ldesc;

            CONST_ID(id_atom, "@atom");
            CONST_ID(id_operand1, "@operand1");
            CONST_ID(id_operand2, "@operand2");
            CONST_ID(id_operand3, "@operand3");
            CONST_ID(id_offset_for_branch, "@offset_for_branch");

            chkerr1(dwarf_get_location_op_value_c(locentry, idx2, &atom, &operand1, &operand2, &operand3, &offset_for_branch, &err),
                    &err, self);
            ldesc = rb_class_new_instance(0, NULL, rd_cLocDesc);
            rb_ivar_set(ldesc, id_atom, rb_hash_aref(rdwarf_op2name, INT2FIX(atom)));
            rb_ivar_set(ldesc, id_operand1, ULL2NUM(operand1));
            rb_ivar_set(ldesc, id_operand2, ULL2NUM(operand2));
            rb_ivar_set(ldesc, id_operand3, ULL2NUM(operand3));
            rb_ivar_set(ldesc, id_offset_for_branch, ULL2NUM(offset_for_branch));
            rb_ary_store(llist, idx2, ldesc);
        }
        rb_ary_store(lhead, idx, llist);
    }
    dwarf_loc_head_c_dealloc(loc_head);
    return lhead;
}
コード例 #3
0
ファイル: dwarf_loc2.c プロジェクト: jrfonseca/drmingw
/*  New October 2015
    This interface requires the use of interface functions
    to get data from Dwarf_Locdesc_c.  The structures
    are not visible to callers. */
int
dwarf_get_loclist_c(Dwarf_Attribute attr,
    Dwarf_Loc_Head_c * ll_header_out,
    Dwarf_Unsigned    * listlen_out,
    Dwarf_Error     * error)
{
    Dwarf_Debug dbg;

    /*  Dwarf_Attribute that describes the DW_AT_location in die, if
        present. */
    Dwarf_Attribute loc_attr = attr;

    /* Dwarf_Block that describes a single location expression. */
    Dwarf_Block_c loc_block;

    Dwarf_Half form = 0;
    Dwarf_Addr lowpc = 0;
    Dwarf_Addr highpc = 0;
    Dwarf_Unsigned     listlen = 0;
    Dwarf_Locdesc_c  llbuf = 0;
    Dwarf_Loc_Head_c llhead = 0;
    Dwarf_CU_Context cucontext = 0;
    unsigned address_size = 0;
    int cuvstamp = 0;
    Dwarf_Bool is_cu = FALSE;

    int blkres = DW_DLV_ERROR;
    int setup_res = DW_DLV_ERROR;

    /* ***** BEGIN CODE ***** */
    setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error);
    if (setup_res != DW_DLV_OK) {
        return setup_res;
    }
    cuvstamp = cucontext->cc_version_stamp;
    address_size = cucontext->cc_address_size;
    /*  If this is a form_block then it's a location expression. If it's
        DW_FORM_data4 or DW_FORM_data8  in DWARF2 or DWARF3
        (or in DWARF4 or 5 a DW_FORM_sec_offset) it's a loclist offset */
    if (((cuvstamp == DW_CU_VERSION2 || cuvstamp == DW_CU_VERSION3) &&
        (form == DW_FORM_data4 || form == DW_FORM_data8)) ||
        ((cuvstamp == DW_CU_VERSION4 || cuvstamp == DW_CU_VERSION5) &&
        form == DW_FORM_sec_offset)) {
        /* Here we have a loclist to deal with. */
        setup_res = context_is_cu_not_tu(cucontext,&is_cu,error);
        if(setup_res != DW_DLV_OK) {
            return setup_res;
        }
        if (cucontext->cc_is_dwo) {
            /*  dwo loclist. If this were a skeleton CU
                (ie, in the base, not dwo/dwp) then
                it could not have a loclist.  */
            /*  A reference to .debug_loc.dwo, with an offset
                in .debug_loc.dwo of a loclist */
            Dwarf_Unsigned loclist_offset = 0;
            int off_res  = DW_DLV_ERROR;
            int count_res = DW_DLV_ERROR;
            int loclist_count = 0;
            Dwarf_Unsigned lli = 0;

            off_res = _dwarf_get_loclist_header_start(dbg,
                attr, &loclist_offset, error);
            if (off_res != DW_DLV_OK) {
                return off_res;
            }
            count_res = _dwarf_get_loclist_count_dwo(dbg, loclist_offset,
                address_size, &loclist_count, error);
            if (count_res != DW_DLV_OK) {
                return count_res;
            }
            listlen = loclist_count;
            if (loclist_count == 0) {
                return DW_DLV_NO_ENTRY;
            }

            llhead = (Dwarf_Loc_Head_c)_dwarf_get_alloc(dbg,
                DW_DLA_LOC_HEAD_C, 1);
            if (!llhead) {
                _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (DW_DLV_ERROR);
            }
            listlen = loclist_count;
            llbuf = (Dwarf_Locdesc_c)
                _dwarf_get_alloc(dbg, DW_DLA_LOCDESC_C, listlen);
            if (!llbuf) {
                dwarf_loc_head_c_dealloc(llhead);
                _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (DW_DLV_ERROR);
            }
            llhead->ll_locdesc = llbuf;
            llhead->ll_locdesc_count = listlen;
            llhead->ll_from_loclist = 2;
            llhead->ll_context = cucontext;
            llhead->ll_dbg = dbg;

            /* New get loc ops, DWO version */
            for (lli = 0; lli < listlen; ++lli) {
                int lres = 0;
                Dwarf_Half lle_op = 0;
                Dwarf_Bool at_end = 0;

                blkres = _dwarf_read_loc_section_dwo(dbg, &loc_block,
                    &lowpc,
                    &highpc,
                    &at_end,
                    &lle_op,
                    loclist_offset,
                    address_size,
                    error);
                if (blkres != DW_DLV_OK) {
                    dwarf_loc_head_c_dealloc(llhead);
                    return blkres;
                }
                /* Fills in the locdesc at index lli */
                lres = _dwarf_get_locdesc_c(dbg,
                    lli,
                    llhead,
                    &loc_block,
                    address_size,
                    cucontext->cc_length_size,
                    cucontext->cc_version_stamp,
                    lowpc,
                    highpc,
                    error);
                if (lres != DW_DLV_OK) {
                    dwarf_loc_head_c_dealloc(llhead);
                    /* low level error already set: let it be passed back */
                    return lres;
                }
                /*  Override the syntesized lle value with the
                    real one. */
                llhead->ll_locdesc[lli].ld_lle_value = lle_op;

                /* Now get to next loclist entry offset. */
                loclist_offset = loc_block.bl_section_offset +
                    loc_block.bl_len;
            }
        } else {
            /*  Non-dwo loclist. If this were a skeleton CU
                (ie, in the base, not dwo/dwp) then
                it could not have a loclist.  */
            /*  A reference to .debug_loc, with an offset
                in .debug_loc of a loclist */
            Dwarf_Unsigned loclist_offset = 0;
            int off_res  = DW_DLV_ERROR;
            int count_res = DW_DLV_ERROR;
            int loclist_count = 0;
            Dwarf_Unsigned lli = 0;

            off_res = _dwarf_get_loclist_header_start(dbg,
                attr, &loclist_offset, error);
            if (off_res != DW_DLV_OK) {
                return off_res;
            }
            count_res = _dwarf_get_loclist_count(dbg, loclist_offset,
                address_size, &loclist_count, error);
            listlen = loclist_count;
            if (count_res != DW_DLV_OK) {
                return count_res;
            }
            if (loclist_count == 0) {
                return DW_DLV_NO_ENTRY;
            }
            llhead = (Dwarf_Loc_Head_c)_dwarf_get_alloc(dbg,
                DW_DLA_LOC_HEAD_C, 1);
            if (!llhead) {
                _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (DW_DLV_ERROR);
            }
            listlen = loclist_count;
            llbuf = (Dwarf_Locdesc_c)
                _dwarf_get_alloc(dbg, DW_DLA_LOCDESC_C, listlen);
            if (!llbuf) {
                dwarf_loc_head_c_dealloc(llhead);
                _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (DW_DLV_ERROR);
            }
            llhead->ll_locdesc = llbuf;
            llhead->ll_locdesc_count = listlen;
            llhead->ll_from_loclist = 1;
            llhead->ll_context = cucontext;
            llhead->ll_dbg = dbg;

            /* New locdesc and Loc,  non-DWO, so old format */
            for (lli = 0; lli < listlen; ++lli) {
                int lres = 0;
                Dwarf_Block_c c;
                blkres = _dwarf_read_loc_section(dbg, &c,
                    &lowpc,
                    &highpc,
                    loclist_offset,
                    address_size,
                    error);
                if (blkres != DW_DLV_OK) {
                    dwarf_loc_head_c_dealloc(llhead);
                    return (blkres);
                }
                loc_block.bl_len = c.bl_len;
                loc_block.bl_data = c.bl_data;
                loc_block.bl_from_loclist = c.bl_from_loclist;
                loc_block.bl_section_offset = c.bl_section_offset;
                loc_block.bl_locdesc_offset = loclist_offset;

                /* Fills in the locdesc at index lli */
                lres = _dwarf_get_locdesc_c(dbg,
                    lli,
                    llhead,
                    &loc_block,
                    address_size,
                    cucontext->cc_length_size,
                    cucontext->cc_version_stamp,
                    lowpc, highpc,
                    error);
                if (lres != DW_DLV_OK) {
                    dwarf_loc_head_c_dealloc(llhead);
                    /*  low level error already set:
                        let it be passed back */
                    return lres;
                }

                /* Now get to next loclist entry offset. */
                loclist_offset = loc_block.bl_section_offset +
                    loc_block.bl_len;
            }
        }
    } else {
        llhead = (Dwarf_Loc_Head_c)
            _dwarf_get_alloc(dbg, DW_DLA_LOC_HEAD_C, 1);
        if (!llhead) {
            _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return (DW_DLV_ERROR);
        }
        if( form == DW_FORM_exprloc) {
            blkres = dwarf_formexprloc(loc_attr,&loc_block.bl_len,
                &loc_block.bl_data,error);
            if(blkres != DW_DLV_OK) {
                dwarf_loc_head_c_dealloc(llhead);
                return blkres;
            }
            loc_block.bl_from_loclist = 0;
            loc_block.bl_section_offset  =
                (char *)loc_block.bl_data -
                (char *)dbg->de_debug_info.dss_data;
            loc_block.bl_locdesc_offset = 0; /* not relevant */
        } else {
            Dwarf_Block *tblock = 0;
            blkres = dwarf_formblock(loc_attr, &tblock, error);
            if (blkres != DW_DLV_OK) {
                dwarf_loc_head_c_dealloc(llhead);
                return (blkres);
            }
            loc_block.bl_len = tblock->bl_len;
            loc_block.bl_data = tblock->bl_data;
            loc_block.bl_from_loclist = tblock->bl_from_loclist;
            loc_block.bl_section_offset = tblock->bl_section_offset;
            loc_block.bl_locdesc_offset = 0; /* not relevant */
            /*  We copied tblock contents to the stack var, so can dealloc
                tblock now.  Avoids leaks. */
            dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK);
        }
        listlen = 1; /* One by definition of a location entry. */
        /*  This hack ensures that the Locdesc_c
            is marked DW_LLE_start_end_entry */
        lowpc = 0;   /* HACK */
        highpc = (Dwarf_Unsigned) (-1LL); /* HACK */

        llbuf = (Dwarf_Locdesc_c)
            _dwarf_get_alloc(dbg, DW_DLA_LOCDESC_C, listlen);
        if (!llbuf) {
            dwarf_loc_head_c_dealloc(llhead);
            _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return (DW_DLV_ERROR);
        }
        llhead->ll_locdesc = llbuf;
        llhead->ll_locdesc = llbuf;
        llhead->ll_locdesc_count = listlen;
        llhead->ll_from_loclist = 0;
        llhead->ll_context = cucontext;
        llhead->ll_dbg = dbg;

        /*  An empty location description (block length 0) means the
            code generator emitted no variable, the variable was not
            generated, it was unused or perhaps never tested after being
            set. Dwarf2, section 2.4.1 In other words, it is not an
            error, and we don't test for block length 0 specially here. */
        /* Fills in the locdesc at index 0 */
        blkres = _dwarf_get_locdesc_c(dbg,
            0, /* fake locdesc is index 0 */
            llhead,
            &loc_block,
            address_size,
            cucontext->cc_length_size,
            cucontext->cc_version_stamp,
            lowpc, highpc,
            error);
        if (blkres != DW_DLV_OK) {
            dwarf_loc_head_c_dealloc(llhead);
            /* low level error already set: let it be passed back */
            return blkres;
        }
    }
    *ll_header_out = llhead;
    *listlen_out = listlen;
    return (DW_DLV_OK);
}