Example #1
0
/*  We encapsulate the macro use so we can
    free local malloc resources that would otherwise
    leak. See the call points below. */
static int
read_unaligned_addr_check(Dwarf_Debug dbg,
    Dwarf_Addr *addr_out,
    Dwarf_Small *rangeptr,
    unsigned address_size,
    Dwarf_Error *error,
    Dwarf_Small *section_end)
{
    Dwarf_Addr a = 0;

    READ_UNALIGNED_CK(dbg,a,
        Dwarf_Addr, rangeptr,
        address_size,
        error,section_end);
    *addr_out = a;
    return DW_DLV_OK;
}
Example #2
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;
}
Example #3
0
int
dwarf_get_xu_index_header(Dwarf_Debug dbg,
    /* Pass in section_type "tu" or "cu" */
    const char *     section_type,
    Dwarf_Xu_Index_Header * xuptr,
    Dwarf_Unsigned * version,
    Dwarf_Unsigned * number_of_columns, /* L */
    Dwarf_Unsigned * number_of_CUs,     /* N */
    Dwarf_Unsigned * number_of_slots,   /* M */
    const char    ** section_name,
    Dwarf_Error    * error)
{
    Dwarf_Xu_Index_Header indexptr = 0;
    int res = DW_DLV_ERROR;
    struct Dwarf_Section_s *sect = 0;
    Dwarf_Unsigned local_version = 0;
    Dwarf_Unsigned num_col  = 0;
    Dwarf_Unsigned num_CUs  = 0;
    Dwarf_Unsigned num_slots  = 0;
    Dwarf_Small *data = 0;
    Dwarf_Unsigned tables_end_offset = 0;
    Dwarf_Unsigned hash_tab_offset = 0;
    Dwarf_Unsigned indexes_tab_offset = 0;
    Dwarf_Unsigned section_offsets_tab_offset = 0;
    Dwarf_Unsigned section_sizes_tab_offset = 0;
    unsigned datalen32 = LEN32BIT;
    Dwarf_Small *section_end = 0;

    if (!strcmp(section_type,"cu") ) {
        sect = &dbg->de_debug_cu_index;
    } else if (!strcmp(section_type,"tu") ) {
        sect = &dbg->de_debug_tu_index;
    } else {
        _dwarf_error(dbg, error, DW_DLE_XU_TYPE_ARG_ERROR);
        return DW_DLV_ERROR;
    }
    if (!sect->dss_size) {
        return DW_DLV_NO_ENTRY;
    }

    if (!sect->dss_data) {
        res = _dwarf_load_section(dbg, sect,error);
        if (res != DW_DLV_OK) {
            return res;
        }
    }

    data = sect->dss_data;
    section_end = data + sect->dss_size;

    if (sect->dss_size < (4*datalen32) ) {
        _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION);
        return (DW_DLV_ERROR);
    }
    READ_UNALIGNED_CK(dbg,local_version, Dwarf_Unsigned,
        data,datalen32,
        error,section_end);
    data += datalen32;
    READ_UNALIGNED_CK(dbg,num_col, Dwarf_Unsigned,
        data,datalen32,
        error,section_end);
    data += datalen32;
    READ_UNALIGNED_CK(dbg,num_CUs, Dwarf_Unsigned,
        data,datalen32,
        error,section_end);
    data += datalen32;
    READ_UNALIGNED_CK(dbg,num_slots, Dwarf_Unsigned,
        data,datalen32,
        error,section_end);
    data += datalen32;
    hash_tab_offset = datalen32*4;
    indexes_tab_offset = hash_tab_offset + (num_slots * HASHSIGNATURELEN);
    /*  Look for corrupt section data. */
    if (num_slots > sect->dss_size) {
        _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION);
        return (DW_DLV_ERROR);
    }
    if ( (4*num_slots) > sect->dss_size) {
        _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION);
        return (DW_DLV_ERROR);
    }

    section_offsets_tab_offset = indexes_tab_offset +
        (num_slots *datalen32);

    if ( num_col > sect->dss_size) {
        /* Something is badly wrong here. */
        _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION);
        return (DW_DLV_ERROR);
    }
    if ( (4*num_col) > sect->dss_size) {
        /* Something is badly wrong here. */
        _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION);
        return (DW_DLV_ERROR);
    }
    section_sizes_tab_offset = section_offsets_tab_offset +
        ((num_CUs +1) *num_col* datalen32) ;
    tables_end_offset = section_sizes_tab_offset +
        ((num_CUs   ) *num_col* datalen32);

    if ( tables_end_offset > sect->dss_size) {
        /* Something is badly wrong here. */
        _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION);
        return (DW_DLV_ERROR);
    }


    indexptr = (Dwarf_Xu_Index_Header)_dwarf_get_alloc(dbg,DW_DLA_XU_INDEX,1);
    if (indexptr == NULL) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }
    strcpy(indexptr->gx_type,section_type);
    indexptr->gx_dbg = dbg;
    indexptr->gx_section_length = sect->dss_size;
    indexptr->gx_section_data   = sect->dss_data;
    indexptr->gx_section_name   = sect->dss_name;
    indexptr->gx_version        = local_version;
    indexptr->gx_column_count_sections = num_col;
    indexptr->gx_units_in_index = num_CUs;
    indexptr->gx_slots_in_hash  = num_slots;
    indexptr->gx_hash_table_offset  =  hash_tab_offset;
    indexptr->gx_index_table_offset  = indexes_tab_offset;
    indexptr->gx_section_offsets_offset  = section_offsets_tab_offset;
    indexptr->gx_section_sizes_offset  = section_sizes_tab_offset;

    *xuptr             =     indexptr;
    *version           = indexptr->gx_version;
    *number_of_columns = indexptr->gx_column_count_sections;
    *number_of_CUs     = indexptr->gx_units_in_index;
    *number_of_slots   = indexptr->gx_slots_in_hash;
    *section_name      = indexptr->gx_section_name;
    return DW_DLV_OK;
}
Example #4
0
static int
_dwarf_read_loc_section_dwo(Dwarf_Debug dbg,
    Dwarf_Block_c * return_block,
    Dwarf_Addr * lowpc,
    Dwarf_Addr * highpc,
    Dwarf_Bool *at_end,
    Dwarf_Half * lle_op,
    Dwarf_Off sec_offset,
    Dwarf_Half address_size,
    Dwarf_Error * error)
{
    Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset;
    Dwarf_Small *locptr = 0;
    Dwarf_Small llecode = 0;
    Dwarf_Word leb128_length = 0;
    Dwarf_Unsigned expr_offset  = sec_offset;
    Dwarf_Byte_Ptr section_end = dbg->de_debug_loc.dss_data
        + dbg->de_debug_loc.dss_size;

    if (sec_offset >= dbg->de_debug_loc.dss_size) {
        /* We're at the end. No more present. */
        return DW_DLV_NO_ENTRY;
    }
    memset(return_block,0,sizeof(*return_block));

    /* not the same as non-split loclist, but still a list. */
    return_block->bl_from_loclist = 2;

    return_block->bl_locdesc_offset = sec_offset;
    llecode = *beg;
    locptr = beg +1;
    expr_offset++;
    switch(llecode) {
    case DW_LLE_end_of_list_entry:
        *at_end = TRUE;
        return_block->bl_section_offset = expr_offset;
        expr_offset++;
        break;
    case DW_LLE_base_address_selection_entry: {
        Dwarf_Unsigned addr_index = 0;

        DECODE_LEB128_UWORD_CK(locptr,addr_index,
            dbg,error,section_end);
        return_block->bl_section_offset = expr_offset;
        /* So this behaves much like non-dwo loclist */
        *lowpc=MAX_ADDR;
        *highpc=addr_index;
        }
        break;
    case DW_LLE_start_end_entry: {
        Dwarf_Unsigned addr_indexs = 0;
        Dwarf_Unsigned addr_indexe= 0;
        Dwarf_Half exprlen = 0;

        DECODE_LEB128_UWORD_CK(locptr,addr_indexs,
            dbg,error,section_end);
        expr_offset += leb128_length;

        DECODE_LEB128_UWORD_CK(locptr,addr_indexe,
            dbg,error,section_end);
        expr_offset +=leb128_length;

        *lowpc=addr_indexs;
        *highpc=addr_indexe;

        READ_UNALIGNED_CK(dbg, exprlen, Dwarf_Half, locptr,
            sizeof(exprlen),
            error,section_end);
        locptr += sizeof(exprlen);
        expr_offset += sizeof(exprlen);

        return_block->bl_len = exprlen;
        return_block->bl_data = locptr;
        return_block->bl_section_offset = expr_offset;

        expr_offset += exprlen;
        if (expr_offset > dbg->de_debug_loc.dss_size) {

            _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
            return DW_DLV_ERROR;
        }
        }
        break;
    case DW_LLE_start_length_entry: {
        Dwarf_Unsigned addr_index = 0;
        Dwarf_ufixed  range_length = 0;
        Dwarf_Half exprlen = 0;

        DECODE_LEB128_UWORD_CK(locptr,addr_index,
            dbg,error,section_end);
        expr_offset +=leb128_length;

        READ_UNALIGNED_CK(dbg, range_length, Dwarf_ufixed, locptr,
            sizeof(range_length),
            error,section_end);
        locptr += sizeof(range_length);
        expr_offset += sizeof(range_length);

        READ_UNALIGNED_CK(dbg, exprlen, Dwarf_Half, locptr,
            sizeof(exprlen),
            error,section_end);
        locptr += sizeof(exprlen);
        expr_offset += sizeof(exprlen);

        *lowpc = addr_index;
        *highpc = range_length;
        return_block->bl_len = exprlen;
        return_block->bl_data = locptr;
        return_block->bl_section_offset = expr_offset;
        /* exprblock_size can be zero, means no expression */

        expr_offset += exprlen;
        if (expr_offset > dbg->de_debug_loc.dss_size) {
            _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
            return DW_DLV_ERROR;
        }
        }
        break;
    case DW_LLE_offset_pair_entry: {
        Dwarf_ufixed  startoffset = 0;
        Dwarf_ufixed  endoffset = 0;
        Dwarf_Half exprlen = 0;

        READ_UNALIGNED_CK(dbg, startoffset, Dwarf_ufixed, locptr,
            sizeof(startoffset),
            error,section_end);
        locptr += sizeof(startoffset);
        expr_offset += sizeof(startoffset);

        READ_UNALIGNED_CK(dbg, endoffset, Dwarf_ufixed, locptr,
            sizeof(endoffset),
            error,section_end);
        locptr += sizeof(endoffset);
        expr_offset += sizeof(endoffset);
        *lowpc= startoffset;
        *highpc = endoffset;

        READ_UNALIGNED_CK(dbg, exprlen, Dwarf_Half, locptr,
            sizeof(exprlen),
            error,section_end);
        locptr += sizeof(exprlen);
        expr_offset += sizeof(exprlen);

        return_block->bl_len = exprlen;
        return_block->bl_data = locptr;
        return_block->bl_section_offset = expr_offset;

        expr_offset += exprlen;
        if (expr_offset > dbg->de_debug_loc.dss_size) {
            _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
            return DW_DLV_ERROR;
        }
        }
        break;
    default:
        _dwarf_error(dbg,error,DW_DLE_LLE_CODE_UNKNOWN);
        return DW_DLV_ERROR;
    }
    *lle_op = llecode;
    return DW_DLV_OK;
}