Exemple #1
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;
}
Exemple #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.

    Returns NULL on error.
*/
Dwarf_Abbrev_List
_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code)
{
    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;
    unsigned hashable_val;

    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 =  _dwarf_get_alloc(dbg,
            DW_DLA_HASH_TABLE_ENTRY, 
            hash_table_base->tb_table_entry_count);
         if(! hash_table_base->tb_entries) {
             return NULL;
         }

    } 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 =  _dwarf_get_alloc(dbg,
            DW_DLA_HASH_TABLE_ENTRY, 
            newht.tb_table_entry_count);

        if(! newht.tb_entries) {
             return NULL;
        }
        /* 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->ab_code != code;
         hash_abbrev_entry = hash_abbrev_entry->ab_next);
    if (hash_abbrev_entry != NULL) {
        /* This returns a pointer to an abbrev list entry, not 
           the list itself. */
        return (hash_abbrev_entry);
    }

    abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ?
        cu_context->cc_last_abbrev_ptr :
        dbg->de_debug_abbrev.dss_data + cu_context->cc_abbrev_offset;

    /* End of abbrev's for this cu, since abbrev code is 0. */
    if (*abbrev_ptr == 0) {
        return (NULL);
    }

    do {
        unsigned new_hashable_val;
        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)
            return (NULL);

        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->ab_next = inner_hash_entry->at_head;
        inner_hash_entry->at_head = inner_list_entry;

        hash_table_base->tb_total_abbrev_count++;

        inner_list_entry->ab_code = abbrev_code;
        inner_list_entry->ab_tag = abbrev_tag;
        inner_list_entry->ab_has_child = *(abbrev_ptr++);
        inner_list_entry->ab_abbrev_ptr = abbrev_ptr;

        /* 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);
        } while (attr_name != 0 && attr_form != 0);

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

    cu_context->cc_last_abbrev_ptr = abbrev_ptr;
    return (abbrev_code == code ? inner_list_entry : NULL);
}