Beispiel #1
0
int
_dwarf_extract_string_offset_via_str_offsets(Dwarf_Debug dbg,
    Dwarf_Small *info_data_ptr,
    Dwarf_Half   attrnum,
    Dwarf_Half   attrform,
    Dwarf_CU_Context cu_context,
    Dwarf_Unsigned *str_sect_offset_out,
    Dwarf_Error *error)
{
    Dwarf_Unsigned offsettostr= 0;
    Dwarf_Unsigned offset_base = 0;
    Dwarf_Word leb_len = 0;
    Dwarf_Unsigned index_to_offset_entry = 0;
    Dwarf_Unsigned offsetintable = 0;
    Dwarf_Unsigned end_offsetintable = 0;
    Dwarf_Unsigned strofflen = 0;
    int res = 0;

    res = _dwarf_load_section(dbg, &dbg->de_debug_str_offsets,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    index_to_offset_entry = (_dwarf_decode_u_leb128(info_data_ptr, &leb_len));
    /*  DW_FORM_GNU_str_index has no 'base' value.
        DW_FORM_strx has a base value
        for the offset table */
    if( attrform == DW_FORM_strx) {
        res = _dwarf_get_string_base_attr_value(dbg,cu_context,
            &offset_base,error);
        if (res != DW_DLV_OK) {
            return res;
        }
    }

    offsetintable = (index_to_offset_entry*cu_context->cc_length_size )
        + offset_base;
    {
        Dwarf_Unsigned fissoff = 0;
        Dwarf_Unsigned size = 0;
        fissoff = _dwarf_get_dwp_extra_offset(&cu_context->cc_dwp_offsets,
            DW_SECT_STR_OFFSETS, &size);
        offsetintable += fissoff;
    }
    end_offsetintable = offsetintable + cu_context->cc_length_size;
    /* The offsets table is a series of offset-size entries. */
    if ((end_offsetintable) >= dbg->de_debug_str_offsets.dss_size ) {
        _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
        return (DW_DLV_ERROR);
    }

    /* Now read the string offset from the offset table. */
    READ_UNALIGNED(dbg,offsettostr,Dwarf_Unsigned,
        dbg->de_debug_str_offsets.dss_data + offsetintable,
        cu_context->cc_length_size);
    *str_sect_offset_out = offsettostr;
    return DW_DLV_OK;
}
Beispiel #2
0
/*  This function returns a pointer to a Dwarf_Abbrev_List_s
    struct for the abbrev with the given code.  It puts the
    struct on the appropriate hash table.  It also adds all
    the abbrev between the last abbrev added and this one to
    the hash table.  In other words, the .debug_abbrev section
    is scanned sequentially from the top for an abbrev with
    the given code.  All intervening abbrevs are also put
    into the hash table.

    This function hashes the given code, and checks the chain
    at that hash table entry to see if a Dwarf_Abbrev_List_s
    with the given code exists.  If yes, it returns a pointer
    to that struct.  Otherwise, it scans the .debug_abbrev
    section from the last byte scanned for that CU till either
    an abbrev with the given code is found, or an abbrev code
    of 0 is read.  It puts Dwarf_Abbrev_List_s entries for all
    abbrev's read till that point into the hash table.  The
    hash table contains both a head pointer and a tail pointer
    for each entry.

    While the lists can move and entries can be moved between
    lists on reallocation, any given Dwarf_Abbrev_list entry
    never moves once allocated, so the pointer is safe to return.

    See also dwarf_get_abbrev() in dwarf_abbrev.c.

    Returns NULL on error.  */
int
_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code,
    Dwarf_Abbrev_List *list_out,
    Dwarf_Error *error)
{
    Dwarf_Debug dbg = cu_context->cc_dbg;
    Dwarf_Hash_Table hash_table_base = cu_context->cc_abbrev_hash_table;
    Dwarf_Hash_Table_Entry entry_base = 0;
    Dwarf_Hash_Table_Entry entry_cur = 0;
    Dwarf_Word hash_num = 0;
    Dwarf_Unsigned abbrev_code = 0;
    Dwarf_Unsigned abbrev_tag  = 0;
    Dwarf_Unsigned attr_name = 0;
    Dwarf_Unsigned attr_form = 0;
    Dwarf_Abbrev_List hash_abbrev_entry = 0;
    Dwarf_Abbrev_List inner_list_entry = 0;
    Dwarf_Hash_Table_Entry inner_hash_entry = 0;

    Dwarf_Byte_Ptr abbrev_ptr = 0;
    Dwarf_Byte_Ptr end_abbrev_ptr = 0;
    unsigned hashable_val = 0;

    if (!hash_table_base->tb_entries) {
        hash_table_base->tb_table_entry_count =  HT_MULTIPLE;
        hash_table_base->tb_total_abbrev_count= 0;
        hash_table_base->tb_entries =
            (struct  Dwarf_Hash_Table_Entry_s *)_dwarf_get_alloc(dbg,
            DW_DLA_HASH_TABLE_ENTRY,
            hash_table_base->tb_table_entry_count);
        if (!hash_table_base->tb_entries) {
            return DW_DLV_NO_ENTRY;
        }

    } else if (hash_table_base->tb_total_abbrev_count >
        ( hash_table_base->tb_table_entry_count * HT_MULTIPLE) ) {
        struct Dwarf_Hash_Table_s newht;
        /* Effectively multiplies by >= HT_MULTIPLE */
        newht.tb_table_entry_count =  hash_table_base->tb_total_abbrev_count;
        newht.tb_total_abbrev_count = 0;
        newht.tb_entries =
            (struct  Dwarf_Hash_Table_Entry_s *)_dwarf_get_alloc(dbg,
            DW_DLA_HASH_TABLE_ENTRY,
            newht.tb_table_entry_count);

        if (!newht.tb_entries) {
            return DW_DLV_NO_ENTRY;
        }
        /*  Copy the existing entries to the new table,
            rehashing each.  */
        copy_abbrev_table_to_new_table(hash_table_base, &newht);
        /*  Dealloc only the entries hash table array, not the lists
            of things pointed to by a hash table entry array. */
        dwarf_dealloc(dbg, hash_table_base->tb_entries,DW_DLA_HASH_TABLE_ENTRY);
        hash_table_base->tb_entries = 0;
        /*  Now overwrite the existing table descriptor with
            the new, newly valid, contents. */
        *hash_table_base = newht;
    } /* Else is ok as is, add entry */

    hashable_val = code;
    hash_num = hashable_val %
        hash_table_base->tb_table_entry_count;
    entry_base = hash_table_base->tb_entries;
    entry_cur  = entry_base + hash_num;

    /* Determine if the 'code' is the list of synonyms already. */
    for (hash_abbrev_entry = entry_cur->at_head;
        hash_abbrev_entry != NULL && hash_abbrev_entry->abl_code != code;
        hash_abbrev_entry = hash_abbrev_entry->abl_next);
    if (hash_abbrev_entry != NULL) {
        /*  This returns a pointer to an abbrev list entry, not
            the list itself. */
        *list_out = hash_abbrev_entry;
        return DW_DLV_OK;
    }

    if (cu_context->cc_last_abbrev_ptr) {
        abbrev_ptr = cu_context->cc_last_abbrev_ptr;
        end_abbrev_ptr = cu_context->cc_last_abbrev_endptr;
    } else {
        /*  This is ok because cc_abbrev_offset includes DWP
            offset if appropriate. */
        abbrev_ptr = dbg->de_debug_abbrev.dss_data +
            cu_context->cc_abbrev_offset;

        if (cu_context->cc_dwp_offsets.pcu_type)  {
            /*  In a DWP the abbrevs
                for this context are known quite precisely. */
            Dwarf_Unsigned size = 0;
            /* Ignore the offset returned. Already in cc_abbrev_offset. */
            _dwarf_get_dwp_extra_offset(&cu_context->cc_dwp_offsets,
                DW_SECT_ABBREV,&size);
            /*  ASSERT: size != 0 */
            end_abbrev_ptr = abbrev_ptr + size;
        } else {
            end_abbrev_ptr = abbrev_ptr +
                dbg->de_debug_abbrev.dss_size;
        }
    }

    /*  End of abbrev's as we are past the end entirely.
        This can happen. */
    if (abbrev_ptr > end_abbrev_ptr) {
        return DW_DLV_NO_ENTRY;
    }
    /*  End of abbrev's for this cu, since abbrev code is 0. */
    if (*abbrev_ptr == 0) {
        return DW_DLV_NO_ENTRY;
    }

    do {
        unsigned new_hashable_val = 0;
        Dwarf_Off  abb_goff = 0;
        Dwarf_Unsigned atcount = 0;

        abb_goff = abbrev_ptr - dbg->de_debug_abbrev.dss_data;
        DECODE_LEB128_UWORD(abbrev_ptr, abbrev_code);
        DECODE_LEB128_UWORD(abbrev_ptr, abbrev_tag);

        inner_list_entry = (Dwarf_Abbrev_List)
            _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1);
        if (inner_list_entry == NULL) {
            _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return DW_DLV_ERROR;
        }

        new_hashable_val = abbrev_code;
        hash_num = new_hashable_val %
            hash_table_base->tb_table_entry_count;
        inner_hash_entry = entry_base + hash_num;
        /* Move_entry_to_new_hash */
        inner_list_entry->abl_next = inner_hash_entry->at_head;
        inner_hash_entry->at_head = inner_list_entry;

        hash_table_base->tb_total_abbrev_count++;

        inner_list_entry->abl_code = abbrev_code;
        inner_list_entry->abl_tag = abbrev_tag;
        inner_list_entry->abl_has_child = *(abbrev_ptr++);
        inner_list_entry->abl_abbrev_ptr = abbrev_ptr;
        inner_list_entry->abl_goffset =  abb_goff;

        hash_table_base->tb_total_abbrev_count++;

        /*  Cycle thru the abbrev content, ignoring the content except
            to find the end of the content. */
        do {
            DECODE_LEB128_UWORD(abbrev_ptr, attr_name);
            DECODE_LEB128_UWORD(abbrev_ptr, attr_form);
            if (!_dwarf_valid_form_we_know(dbg,attr_form,attr_name)) {
                _dwarf_error(dbg,error,DW_DLE_UNKNOWN_FORM);
                return DW_DLV_ERROR;
            }
            atcount++;
        } while (attr_name != 0 && attr_form != 0);
        /*  We counted one too high, by counting the NUL
            byte pair at end of list. So decrement. */
        inner_list_entry->abl_count = atcount-1;

        /*  We may have fallen off the end of content,  that is not
            a botch in the section, as there is no rule that the last
            abbrev need have abbrev_code of 0. */

    } while ((abbrev_ptr < end_abbrev_ptr) &&
        *abbrev_ptr != 0 && abbrev_code != code);

    cu_context->cc_last_abbrev_ptr = abbrev_ptr;
    cu_context->cc_last_abbrev_endptr = end_abbrev_ptr;
    if(abbrev_code == code) {
        *list_out = inner_list_entry;
        return DW_DLV_OK;
    }
    return DW_DLV_NO_ENTRY;
}
Beispiel #3
0
int
_dwarf_extract_string_offset_via_str_offsets(Dwarf_Debug dbg,
    Dwarf_Small *info_data_ptr,
    UNUSEDARG Dwarf_Half   attrnum,
    Dwarf_Half   attrform,
    Dwarf_CU_Context cu_context,
    Dwarf_Unsigned *str_sect_offset_out,
    Dwarf_Error *error)
{
    Dwarf_Unsigned offsettostr= 0;
    Dwarf_Unsigned offset_base = 0;
    Dwarf_Word leb_len = 0;
    Dwarf_Unsigned index_to_offset_entry = 0;
    Dwarf_Unsigned offsetintable = 0;
    Dwarf_Unsigned end_offsetintable = 0;
    int res = 0;

    res = _dwarf_load_section(dbg, &dbg->de_debug_str_offsets,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    index_to_offset_entry = (_dwarf_decode_u_leb128(info_data_ptr, &leb_len));
    /*  DW_FORM_GNU_str_index has no 'base' value.
        DW_FORM_strx has a base value
        for the offset table */
    if( attrform == DW_FORM_strx) {
        res = _dwarf_get_string_base_attr_value(dbg,cu_context,
            &offset_base,error);
        if (res != DW_DLV_OK) {
            /*  DW_DLV_NO_ENTRY could be acceptable when
                a producer knows that the base offset will be zero.
                Hence DW_AT_str_offsets_base missing.
                DWARF5 draft as of September 2015 allows the attribute
                to be missing (it's up to the compilation tools to
                make sure that has the correct effect).
            */
            return res;
        }
    }

    offsetintable = (index_to_offset_entry*cu_context->cc_length_size )
        + offset_base;
    {
        Dwarf_Unsigned fissoff = 0;
        Dwarf_Unsigned size = 0;
        fissoff = _dwarf_get_dwp_extra_offset(&cu_context->cc_dwp_offsets,
            DW_SECT_STR_OFFSETS, &size);
        offsetintable += fissoff;
    }
    end_offsetintable = offsetintable + cu_context->cc_length_size;
    /*  The offsets table is a series of offset-size entries.
        The == case in the test applies when we are at the last table
        entry, so == is not an error, hence only test >
    */
    if (end_offsetintable > dbg->de_debug_str_offsets.dss_size ) {
        _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
        return (DW_DLV_ERROR);
    }

    /* Now read the string offset from the offset table. */
    READ_UNALIGNED(dbg,offsettostr,Dwarf_Unsigned,
        dbg->de_debug_str_offsets.dss_data + offsetintable,
        cu_context->cc_length_size);
    *str_sect_offset_out = offsettostr;
    return DW_DLV_OK;
}