Beispiel #1
0
MonoDebugMethodAddressList *
mono_debug_lookup_method_addresses (MonoMethod *method)
{
	MonoDebugMethodAddressList *info;
	MonoDebugMethodHeader *header = NULL;
	struct LookupMethodAddressData data;
	MonoMethod *declaring;
	int count, size;
	GSList *list;
	guint8 *ptr;

	g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));

	mono_debugger_lock ();

	declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;

	data.method = declaring;
	data.result = NULL;

	g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
	header = data.result;

	if (!header) {
		mono_debugger_unlock ();
		return NULL;
	}

	count = g_slist_length (header->address_list) + 1;
	size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);

	info = g_malloc0 (size);
	info->size = size;
	info->count = count;

	ptr = info->data;

	WRITE_UNALIGNED (gpointer, ptr, header);
	ptr += sizeof (gpointer);

	for (list = header->address_list; list; list = list->next) {
		WRITE_UNALIGNED (gpointer, ptr, list->data);
		ptr += sizeof (gpointer);
	}

	mono_debugger_unlock ();
	return info;
}
Beispiel #2
0
/* Make sure attribute types are checked before entering here. */
static Dwarf_P_Attribute
local_add_AT_address(Dwarf_P_Debug dbg,
    Dwarf_P_Die ownerdie,
    Dwarf_Half attr,
    Dwarf_Signed form,
    Dwarf_Unsigned pc_value,
    Dwarf_Unsigned sym_index,
    Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    int upointer_size = 0;

    if (dbg == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    upointer_size = dbg->de_pointer_size;

    if (ownerdie == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    /* attribute types have already been checked */
    /* switch (attr) { ... } */

    new_attr = (Dwarf_P_Attribute)
        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = form;
    new_attr->ar_nbytes = upointer_size;
    new_attr->ar_rel_symidx = sym_index;
    new_attr->ar_reloc_len = upointer_size;
    new_attr->ar_next = 0;
    if (sym_index != NO_ELF_SYM_INDEX) {
        new_attr->ar_rel_type = dbg->de_ptr_reloc;
    } else {
        new_attr->ar_rel_type = R_MIPS_NONE;
    }

    new_attr->ar_data = (char *)
        _dwarf_p_get_alloc(dbg, upointer_size);
    if (new_attr->ar_data == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    WRITE_UNALIGNED(dbg, new_attr->ar_data,
        (const void *) &pc_value,
        sizeof(pc_value), upointer_size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Beispiel #3
0
static void
mono_debug_add_type (MonoClass *klass)
{
	MonoDebugHandle *handle;
	MonoDebugClassEntry *entry;
	guint8 buffer [BUFSIZ];
	guint8 *ptr, *oldptr;
	guint32 size, total_size, max_size;
	int base_offset = 0;

	if (klass->generic_class || klass->rank ||
	    (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
		return;

	mono_debugger_lock ();

	handle = _mono_debug_get_image (klass->image);
	if (!handle) {
		mono_debugger_unlock ();
		return;
	}

	max_size = 12 + sizeof (gpointer);
	if (max_size > BUFSIZ)
		ptr = oldptr = g_malloc (max_size);
	else
		ptr = oldptr = buffer;

	if (klass->valuetype)
		base_offset = - (int)(sizeof (MonoObject));

	write_leb128 (klass->type_token, ptr, &ptr);
	write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
	WRITE_UNALIGNED (gpointer, ptr, klass);
	ptr += sizeof (gpointer);

	size = ptr - oldptr;
	g_assert (size < max_size);
	total_size = size + sizeof (MonoDebugClassEntry);

	g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);

	entry = (MonoDebugClassEntry *) allocate_data_item (
		handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);

	entry->size = total_size;

	memcpy (&entry->data, oldptr, size);

	write_data_item (handle->type_table, (guint8 *) entry);

	if (max_size > BUFSIZ)
		g_free (oldptr);

	mono_debugger_unlock ();
}
Beispiel #4
0
static void
write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
{
	write_leb128 (var->index, ptr, &ptr);
	write_sleb128 (var->offset, ptr, &ptr);
	write_leb128 (var->size, ptr, &ptr);
	write_leb128 (var->begin_scope, ptr, &ptr);
	write_leb128 (var->end_scope, ptr, &ptr);
	WRITE_UNALIGNED (gpointer, ptr, var->type);
	ptr += sizeof (gpointer);
	*rptr = ptr;
}
Beispiel #5
0
Dwarf_Unsigned
dwarf_add_expr_addr_b (
    Dwarf_P_Expr	expr,
    Dwarf_Unsigned	addr,
    Dwarf_Unsigned	sym_index,
    Dwarf_Error		*error
)
{
    Dwarf_P_Debug		dbg;
    Dwarf_Small		*next_byte_ptr;
    Dwarf_Unsigned	next_byte_offset;
    int upointer_size;

    if (expr == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
	return(DW_DLV_NOCOUNT);
    }

    dbg = expr->ex_dbg;
    if (dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return(DW_DLV_NOCOUNT);
    }

    upointer_size = dbg->de_pointer_size;
    next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1;
    if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
	_dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	return(DW_DLV_NOCOUNT);
    }

    next_byte_ptr = &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;

    *next_byte_ptr = DW_OP_addr;
    next_byte_ptr++;
    WRITE_UNALIGNED (dbg,next_byte_ptr,(const void *)&addr,
		sizeof(addr),upointer_size);

    if (expr->ex_reloc_offset != 0) {
	_dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR);
	return(DW_DLV_NOCOUNT);
    }

    expr->ex_reloc_sym_index = sym_index;
    expr->ex_reloc_offset = expr->ex_next_byte_offset + 1;

    expr->ex_next_byte_offset = next_byte_offset;
    return(next_byte_offset);
}
Beispiel #6
0
int
_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,
			     Dwarf_P_Die die,
			     Dwarf_Unsigned offset, Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    int uwordb_size = dbg->de_offset_size;

    if (die == NULL) {
	DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1);
    }
    new_attr = (Dwarf_P_Attribute)
        _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1);
    }

    /* fill in the information */
    new_attr->ar_attribute = DW_AT_macro_info;
    new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
    new_attr->ar_rel_type = dbg->de_offset_reloc;

    new_attr->ar_nbytes = uwordb_size;
    new_attr->ar_next = NULL;
    new_attr->ar_reloc_len = uwordb_size;
    new_attr->ar_data = (char *)
        _dwarf_p_get_alloc(dbg, uwordb_size);
    if (new_attr->ar_data == NULL) {
	DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT);
    }
    {
	Dwarf_Unsigned du = offset;

	WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
			(const void *) &du, sizeof(du), uwordb_size);
    }

    _dwarf_pro_add_at_to_die(die, new_attr);

    return 0;
}
Beispiel #7
0
int
_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,
			    Dwarf_P_Die first_die, Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    int uwordb_size = dbg->de_offset_size;

    /* Add AT_stmt_list attribute */
    new_attr = (Dwarf_P_Attribute)
	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT);
    }

    new_attr->ar_attribute = DW_AT_stmt_list;
    new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
    new_attr->ar_rel_type = dbg->de_offset_reloc;

    new_attr->ar_nbytes = uwordb_size;
    new_attr->ar_next = NULL;
    new_attr->ar_reloc_len = uwordb_size;
    new_attr->ar_data = (char *)
	_dwarf_p_get_alloc(dbg, uwordb_size);
    if (new_attr->ar_data == NULL) {
	DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT);
    }
    {
	Dwarf_Unsigned du = 0;

	WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
			(const void *) &du, sizeof(du), uwordb_size);
    }

    _dwarf_pro_add_at_to_die(first_die, new_attr);
    return 0;
}
Beispiel #8
0
int
_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg,
    Dwarf_Signed *nbufs, Dwarf_Error * error)
{
    /* Total num of bytes in .debug_aranges section. */
    Dwarf_Unsigned arange_num_bytes = 0;

    /*  Adjustment to align the start of the actual address ranges on a
        boundary aligned with twice the address size. */
    Dwarf_Small remainder = 0;

    /*  Total number of bytes excluding the length field. */
    Dwarf_Unsigned adjusted_length = 0;

    /*  Points to first byte of .debug_aranges buffer. */
    Dwarf_Small *arange = 0;

    /*  Fills in the .debug_aranges buffer. */
    Dwarf_Small *arange_ptr = 0;

    /*  Scans the list of address ranges provided by user. */
    Dwarf_P_Arange given_arange = 0;

    /*  Used to fill in 0. */
    const Dwarf_Signed big_zero = 0;

    int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
    int offset_size = dbg->de_offset_size;
    int upointer_size = dbg->de_pointer_size;

    /*  All dwarf versions so far use 2 here. */
    Dwarf_Half version = 2;
    int res = 0;


    /* ***** BEGIN CODE ***** */

    /* Size of the .debug_aranges section header. */
    arange_num_bytes = extension_word_size +
        offset_size +       /* Size of length field.  */
        DWARF_HALF_SIZE +    /* Size of version field. */
        offset_size +            /* Size of .debug_info offset. */
        sizeof(Dwarf_Small) +   /* Size of address size field. */
        sizeof(Dwarf_Small);    /* Size of segment size field. */

    /*  Adjust the size so that the set of aranges begins on a boundary
        that aligned with twice the address size.  This is a Libdwarf
        requirement. */
    remainder = arange_num_bytes % (2 * upointer_size);
    if (remainder != 0)
        arange_num_bytes += (2 * upointer_size) - remainder;


    /* Add the bytes for the actual address ranges. */
    arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);

    GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
        arange, (unsigned long) arange_num_bytes, error);
    arange_ptr = arange;
    if (extension_word_size) {
        Dwarf_Word x = DISTINGUISHED_VALUE;

        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &x,
            sizeof(x), extension_word_size);
        arange_ptr += extension_word_size;
    }

    /* Write the total length of .debug_aranges section. */
    adjusted_length = arange_num_bytes - offset_size
        - extension_word_size;
    {
        Dwarf_Unsigned du = adjusted_length;

        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &du, sizeof(du), offset_size);
        arange_ptr += offset_size;
    }

    /* Write the version as 2 bytes. */
    {
        Dwarf_Half verstamp = version;

        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &verstamp,
            sizeof(verstamp), DWARF_HALF_SIZE);
        arange_ptr += DWARF_HALF_SIZE;
    }


    /* Write the .debug_info offset.  This is always 0. */
    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
        (const void *) &big_zero,
        sizeof(big_zero), offset_size);
    arange_ptr += offset_size;

    {
        unsigned long count = dbg->de_arange_count + 1;
        int res2 = 0;
        Dwarf_P_Per_Reloc_Sect p_reloc =
            &dbg->de_reloc_sect[DEBUG_ARANGES];

        if (dbg->de_relocate_pair_by_symbol) {
            count = (3 * dbg->de_arange_count) + 1;
        }
        /*  The following is a small optimization: not needed for
            correctness.  Does nothing if
            preloc->pr_first_block is non-null */
        res2 = _dwarf_pro_pre_alloc_specific_reloc_slots(dbg,
            p_reloc, count);
        if (res2 != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return DW_DLV_ERROR;
        }
    }

    /* reloc for .debug_info */
    res = dbg->de_relocate_by_name_symbol(dbg,
        DEBUG_ARANGES,
        extension_word_size +
        offset_size + DWARF_HALF_SIZE,
        dbg->de_sect_name_idx[DEBUG_INFO],
        dwarf_drt_data_reloc, offset_size);

    /* Write the size of addresses. */
    *arange_ptr = dbg->de_pointer_size;
    arange_ptr++;

    /*  Write the size of segment addresses. This is zero for MIPS
        architectures. */
    *arange_ptr = 0;
    arange_ptr++;

    /*  Skip over the padding to align the start of the actual address
        ranges to twice the address size. */
    if (remainder != 0)
        arange_ptr += (2 * upointer_size) - remainder;





    /*  The arange address, length are pointer-size fields of the target
        machine. */
    for (given_arange = dbg->de_arange; given_arange != NULL;
        given_arange = given_arange->ag_next) {

        /* Write relocation record for beginning of address range. */
        res = dbg->de_relocate_by_name_symbol(dbg, DEBUG_ARANGES,
            arange_ptr - arange,       /* r_offset */
            (long) given_arange->ag_symbol_index,
            dwarf_drt_data_reloc, upointer_size);
        if (res != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return DW_DLV_ERROR;
        }

        /* Copy beginning address of range. */
        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &given_arange->ag_begin_address,
            sizeof(given_arange->ag_begin_address),
            upointer_size);
        arange_ptr += upointer_size;

        if (dbg->de_relocate_pair_by_symbol &&
            given_arange->ag_end_symbol_index != 0 &&
            given_arange->ag_length == 0) {
            /*  symbolic reloc, need reloc for length What if we really
                know the length? If so, should use the other part of
                'if'. */
            Dwarf_Unsigned val;

            res = dbg->de_relocate_pair_by_symbol(dbg,
                DEBUG_ARANGES,
                arange_ptr - arange,   /* r_offset */
                given_arange->ag_symbol_index,
                given_arange->ag_end_symbol_index,
                dwarf_drt_first_of_length_pair,
                upointer_size);
            if (res != DW_DLV_OK) {
                _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return DW_DLV_ERROR;
            }

            /*  arange pre-calc so assem text can do .word end - begin
                + val (gets val from stream) */
            val = given_arange->ag_end_symbol_offset -
                given_arange->ag_begin_address;
            WRITE_UNALIGNED(dbg, (void *) arange_ptr,
                (const void *) &val,
                sizeof(val), upointer_size);
            arange_ptr += upointer_size;

        } else {
            /* plain old length to copy, no relocation at all */
            WRITE_UNALIGNED(dbg, (void *) arange_ptr,
                (const void *) &given_arange->ag_length,
                sizeof(given_arange->ag_length),
                upointer_size);
            arange_ptr += upointer_size;
        }
    }

    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
        (const void *) &big_zero,
        sizeof(big_zero), upointer_size);

    arange_ptr += upointer_size;
    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
        (const void *) &big_zero,
        sizeof(big_zero), upointer_size);
    *nbufs =  dbg->de_n_debug_sect;
    return DW_DLV_OK;
}
Beispiel #9
0
Dwarf_Unsigned
dwarf_add_expr_gen (
    Dwarf_P_Expr	expr,
    Dwarf_Small		opcode,
    Dwarf_Unsigned	val1,
    Dwarf_Unsigned	val2,
    Dwarf_Error		*error
)
{
    char encode_buffer[2*ENCODE_SPACE_NEEDED]; /* 2* since used
		to concatenate 2 leb's below */
    char encode_buffer2[ENCODE_SPACE_NEEDED];
    int  res;
    Dwarf_P_Debug dbg = expr->ex_dbg;
	/* 
	    Give the buffer where the operands are first
	    going to be assembled the largest alignment.
	*/
    Dwarf_Unsigned	operand_buffer[10];

	/* 
	    Size of the byte stream buffer that needs 
	    to be memcpy-ed.
	*/
    int			operand_size;

	/* 
	    Points to the byte stream for the first operand,
	    and finally to the buffer that is memcp-ed into
	    the Dwarf_P_Expr_s struct.
	*/
    Dwarf_Small		*operand;

	/* Size of the byte stream for second operand. */
    int			operand2_size;

	/* Points to next byte to be written in Dwarf_P_Expr_s struct. */
    Dwarf_Small		*next_byte_ptr;

	/* Offset past the last byte written into Dwarf_P_Expr_s. */
    int			next_byte_offset;

    /* ***** BEGIN CODE ***** */

    if (expr == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
	return(DW_DLV_NOCOUNT);
    }

    if (expr->ex_dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return(DW_DLV_NOCOUNT);
    }

    operand = NULL;
    operand_size = 0;

    switch (opcode) {
        case DW_OP_reg0 :
	case DW_OP_reg1 :
	case DW_OP_reg2 :
	case DW_OP_reg3 :
	case DW_OP_reg4 :
	case DW_OP_reg5 :
	case DW_OP_reg6 :
	case DW_OP_reg7 :
	case DW_OP_reg8 :
	case DW_OP_reg9 :
	case DW_OP_reg10 :
	case DW_OP_reg11 :
	case DW_OP_reg12 :
	case DW_OP_reg13 :
	case DW_OP_reg14 :
	case DW_OP_reg15 :
	case DW_OP_reg16 :
	case DW_OP_reg17 :
	case DW_OP_reg18 :
	case DW_OP_reg19 :
	case DW_OP_reg20 :
	case DW_OP_reg21 :
	case DW_OP_reg22 :
	case DW_OP_reg23 :
	case DW_OP_reg24 :
	case DW_OP_reg25 :
	case DW_OP_reg26 :
	case DW_OP_reg27 :
	case DW_OP_reg28 :
	case DW_OP_reg29 :
	case DW_OP_reg30 :
	case DW_OP_reg31 :
	    break;

	case DW_OP_breg0 :
	case DW_OP_breg1 :
	case DW_OP_breg2 :
	case DW_OP_breg3 :
	case DW_OP_breg4 :
	case DW_OP_breg5 :
	case DW_OP_breg6 :
	case DW_OP_breg7 :
	case DW_OP_breg8 :
	case DW_OP_breg9 :
	case DW_OP_breg10 :
	case DW_OP_breg11 :
	case DW_OP_breg12 :
	case DW_OP_breg13 :
	case DW_OP_breg14 :
	case DW_OP_breg15 :
	case DW_OP_breg16 :
	case DW_OP_breg17 :
	case DW_OP_breg18 :
	case DW_OP_breg19 :
	case DW_OP_breg20 :
	case DW_OP_breg21 :
	case DW_OP_breg22 :
	case DW_OP_breg23 :
	case DW_OP_breg24 :
	case DW_OP_breg25 :
	case DW_OP_breg26 :
	case DW_OP_breg27 :
	case DW_OP_breg28 :
	case DW_OP_breg29 :
	case DW_OP_breg30 :
	case DW_OP_breg31 :
	    res = _dwarf_pro_encode_signed_leb128_nm(val1, 
			&operand_size,encode_buffer,sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

        case DW_OP_regx :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_lit0 :
	case DW_OP_lit1 :
	case DW_OP_lit2 :
	case DW_OP_lit3 :
	case DW_OP_lit4 :
	case DW_OP_lit5 :
	case DW_OP_lit6 :
	case DW_OP_lit7 :
	case DW_OP_lit8 :
	case DW_OP_lit9 :
	case DW_OP_lit10 :
	case DW_OP_lit11 :
	case DW_OP_lit12 :
	case DW_OP_lit13 :
	case DW_OP_lit14 :
	case DW_OP_lit15 :
	case DW_OP_lit16 :
	case DW_OP_lit17 :
	case DW_OP_lit18 :
	case DW_OP_lit19 :
	case DW_OP_lit20 :
	case DW_OP_lit21 :
	case DW_OP_lit22 :
	case DW_OP_lit23 :
	case DW_OP_lit24 :
	case DW_OP_lit25 :
	case DW_OP_lit26 :
	case DW_OP_lit27 :
	case DW_OP_lit28 :
	case DW_OP_lit29 :
	case DW_OP_lit30 :
	case DW_OP_lit31 :
	    break;
        
	case DW_OP_addr :
	    _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
	    return(DW_DLV_NOCOUNT);

	case DW_OP_const1u :
	case DW_OP_const1s :
            operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),1);
	    operand_size = 1;
	    break;

	case DW_OP_const2u :
	case DW_OP_const2s :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),2);
	    operand_size = 2;
	    break;

	case DW_OP_const4u :
	case DW_OP_const4s :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),4);
	    operand_size = 4;
	    break;

	case DW_OP_const8u :
	case DW_OP_const8s :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),8);
	    operand_size = 8;
	    break;

        case DW_OP_constu :
	    res = _dwarf_pro_encode_leb128_nm(val1, 
			&operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_consts :
	    res = _dwarf_pro_encode_signed_leb128_nm(val1, 
			&operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_fbreg :
	    res = _dwarf_pro_encode_signed_leb128_nm(val1, 
			&operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_bregx :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
		/* put this one directly into 'operand' at tail of
		   prev value
	 	*/
	    res =  _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size,
			((char *)operand)+operand_size, sizeof(encode_buffer2));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand_size += operand2_size;

	case DW_OP_dup :
	case DW_OP_drop :
	    break;

	case DW_OP_pick :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,(const void *)val1,
			sizeof(val1),1);
	    operand_size = 1;
	    break;

	case DW_OP_over :
	case DW_OP_swap :
	case DW_OP_rot :
	case DW_OP_deref :
	case DW_OP_xderef :
            break;

	case DW_OP_deref_size :
	case DW_OP_xderef_size :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,(const void *)val1,
			sizeof(val1),1);
	    operand_size = 1;
	    break;

        case DW_OP_abs :
	case DW_OP_and :
	case DW_OP_div :
	case DW_OP_minus :
	case DW_OP_mod :
	case DW_OP_mul :
	case DW_OP_neg :
	case DW_OP_not :
	case DW_OP_or :
	case DW_OP_plus :
	    break;

	case DW_OP_plus_uconst :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_shl :
	case DW_OP_shr :
	case DW_OP_shra :
	case DW_OP_xor :
	    break;

	case DW_OP_le :
	case DW_OP_ge :
	case DW_OP_eq :
	case DW_OP_lt :
	case DW_OP_gt :
	case DW_OP_ne :
	    break;

	case DW_OP_skip :
	case DW_OP_bra :
            /* FIX: unhandled! OP_bra, OP_skip! */
	    _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
	    return(DW_DLV_NOCOUNT);

	case DW_OP_piece :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_nop :
	    break;

	default :
	    _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
	    return(DW_DLV_NOCOUNT);
    }

    next_byte_offset = expr->ex_next_byte_offset + operand_size + 1;

    if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
	_dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	return(DW_DLV_NOCOUNT);
    }

    next_byte_ptr = &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;

    *next_byte_ptr = opcode;
    next_byte_ptr++;
    memcpy(next_byte_ptr, operand, operand_size);

    expr->ex_next_byte_offset = next_byte_offset;
    return(next_byte_offset);
}
Beispiel #10
0
/* new interface */
Dwarf_P_Attribute
dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg,
			    Dwarf_P_Die ownerdie,
			    Dwarf_Half attr,
			    Dwarf_Unsigned pc_value,
			    Dwarf_Unsigned sym_index,
			    Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    int upointer_size = dbg->de_pointer_size;

    if (dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (ownerdie == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (attr != DW_AT_low_pc && attr != DW_AT_high_pc &&
	attr != DW_AT_MIPS_loop_begin &&
	attr != DW_AT_MIPS_tail_loop_begin &&
	attr != DW_AT_MIPS_epilog_begin) {
	_dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr = (Dwarf_P_Attribute)
	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = DW_FORM_addr;
    new_attr->ar_nbytes = upointer_size;
    new_attr->ar_rel_symidx = sym_index;
    new_attr->ar_reloc_len = upointer_size;
    new_attr->ar_next = 0;
    if (sym_index != NO_ELF_SYM_INDEX)
	new_attr->ar_rel_type = dbg->de_ptr_reloc;
    else
	new_attr->ar_rel_type = R_MIPS_NONE;

    new_attr->ar_data = (char *)
	_dwarf_p_get_alloc(dbg, upointer_size);
    if (new_attr->ar_data == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    WRITE_UNALIGNED(dbg, new_attr->ar_data,
		    (const void *) &pc_value,
		    sizeof(pc_value), upointer_size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Beispiel #11
0
/*
    This function adds attributes whose value
    is a location expression.
*/
Dwarf_P_Attribute
dwarf_add_AT_location_expr(Dwarf_P_Debug dbg,
			   Dwarf_P_Die ownerdie,
			   Dwarf_Half attr,
			   Dwarf_P_Expr loc_expr, Dwarf_Error * error)
{
    char encode_buffer[ENCODE_SPACE_NEEDED];
    int res;
    Dwarf_P_Attribute new_attr;
    Dwarf_Half attr_form;
    char *len_str;
    int len_size;
    int block_size;
    char *block_dest_ptr;
    int do_len_as_int = 0;

    if (dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (ownerdie == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (loc_expr == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (loc_expr->ex_dbg != dbg) {
	_dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    block_size = loc_expr->ex_next_byte_offset;

    switch (attr) {
    case DW_AT_location:
    case DW_AT_string_length:
    case DW_AT_const_value:
    case DW_AT_use_location:
    case DW_AT_return_addr:
    case DW_AT_data_member_location:
    case DW_AT_frame_base:
    case DW_AT_static_link:
    case DW_AT_vtable_elem_location:
	break;

    default:{
	    _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
    }

    /* 
       Compute the number of bytes needed to hold constant. */
    if (block_size <= UCHAR_MAX) {
	attr_form = DW_FORM_block1;
	len_size = 1;
	do_len_as_int = 1;
    } else if (block_size <= USHRT_MAX) {
	attr_form = DW_FORM_block2;
	len_size = 2;
	do_len_as_int = 1;
    } else if (block_size <= UINT_MAX) {
	attr_form = DW_FORM_block4;
	len_size = 4;
	do_len_as_int = 1;
    } else {
	attr_form = DW_FORM_block;
	res = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
					  encode_buffer,
					  sizeof(encode_buffer));
	if (res != DW_DLV_OK) {
	    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
	len_str = (char *) encode_buffer;
    }

    new_attr = (Dwarf_P_Attribute)
	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = attr_form;
    new_attr->ar_reloc_len = dbg->de_pointer_size;
    if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) {
	new_attr->ar_rel_type = dbg->de_ptr_reloc;
    } else {
	new_attr->ar_rel_type = R_MIPS_NONE;
    }
    new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index;
    new_attr->ar_rel_offset =
	(Dwarf_Word) loc_expr->ex_reloc_offset + len_size;

    new_attr->ar_nbytes = block_size + len_size;

    new_attr->ar_next = 0;
    new_attr->ar_data = block_dest_ptr =
	(char *) _dwarf_p_get_alloc(dbg, block_size + len_size);
    if (new_attr->ar_data == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (do_len_as_int) {
	WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size,
			sizeof(block_size), len_size);
    } else {
	/* is uleb number form */
	memcpy(block_dest_ptr, len_str, len_size);
    }
    block_dest_ptr += len_size;
    memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Beispiel #12
0
/*
    This function adds attributes whose value
    is an signed constant.  It determines the 
    size of the value field from the value of 
    the constant.
*/
Dwarf_P_Attribute
dwarf_add_AT_signed_const(Dwarf_P_Debug dbg,
			  Dwarf_P_Die ownerdie,
			  Dwarf_Half attr,
			  Dwarf_Signed value, Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    Dwarf_Half attr_form;
    Dwarf_Small size;

    if (dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (ownerdie == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    switch (attr) {
    case DW_AT_upper_bound:
    case DW_AT_lower_bound:
	break;

    default:{
	    _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
    }

    /* Compute the number of bytes needed to hold constant.
       gdb seems to treat all the DW_FORM_data forms as unsigned, so
       if we have a negative number we need to encode it as signed
       data. */
    new_attr = (Dwarf_P_Attribute)
	_dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (value < 0) {
	attr_form = DW_FORM_sdata;
    } else if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
	attr_form = DW_FORM_data1;
	size = 1;
    } else if (value >= SHRT_MIN && value <= SHRT_MAX) {
	attr_form = DW_FORM_data2;
	size = 2;
    } else if (value >= INT_MIN && value <= INT_MAX) {
	attr_form = DW_FORM_data4;
	size = 4;
    } else {
	attr_form = DW_FORM_data8;
	size = 8;
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = attr_form;
    new_attr->ar_rel_type = R_MIPS_NONE;
    new_attr->ar_reloc_len = 0;	/* irrelevant: unused with R_MIPS_NONE 
				 */
    new_attr->ar_nbytes = size;
    new_attr->ar_next = 0;

    if (attr_form == DW_FORM_sdata) {
        int leb_size;
        char encode_buffer[ENCODE_SPACE_NEEDED];
        int res;

        res = _dwarf_pro_encode_signed_leb128_nm(
	    value, &leb_size,
	    encode_buffer,sizeof(encode_buffer));
        if (res != DW_DLV_OK) {
            _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
            return (Dwarf_P_Attribute) DW_DLV_BADADDR;
        }
        new_attr->ar_data = (char *) _dwarf_p_get_alloc(NULL, leb_size);
        if (new_attr->ar_data == NULL) {
            _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
            return (Dwarf_P_Attribute) DW_DLV_BADADDR;
        }
        memcpy(new_attr->ar_data,encode_buffer,leb_size);
        new_attr->ar_nbytes = leb_size;
    } else {
	new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, size);
	if (new_attr->ar_data == NULL) {
	    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
	WRITE_UNALIGNED(dbg, new_attr->ar_data,
			(const void *) &value, sizeof(value), size);
    }


    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Beispiel #13
0
/*
    This function adds attributes whose value
    is an unsigned constant.  It determines the 
    size of the value field from the value of 
    the constant.
*/
Dwarf_P_Attribute
dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg,
			    Dwarf_P_Die ownerdie,
			    Dwarf_Half attr,
			    Dwarf_Unsigned value, Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    Dwarf_Half attr_form;
    Dwarf_Small size;

    if (dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (ownerdie == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    switch (attr) {
    case DW_AT_ordering:
    case DW_AT_byte_size:
    case DW_AT_bit_offset:
    case DW_AT_bit_size:
    case DW_AT_inline:
    case DW_AT_language:
    case DW_AT_visibility:
    case DW_AT_virtuality:
    case DW_AT_accessibility:
    case DW_AT_address_class:
    case DW_AT_calling_convention:
    case DW_AT_encoding:
    case DW_AT_identifier_case:
    case DW_AT_MIPS_loop_unroll_factor:
    case DW_AT_MIPS_software_pipeline_depth:
	break;

    case DW_AT_decl_column:
    case DW_AT_decl_file:
    case DW_AT_decl_line:
    case DW_AT_const_value:
    case DW_AT_start_scope:
    case DW_AT_stride_size:
    case DW_AT_count:
	break;

    default:{
	    _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
    }

    /* 
       Compute the number of bytes needed to hold constant. */
    if (value <= UCHAR_MAX) {
	attr_form = DW_FORM_data1;
	size = 1;
    } else if (value <= USHRT_MAX) {
	attr_form = DW_FORM_data2;
	size = 2;
    } else if (value <= UINT_MAX) {
	attr_form = DW_FORM_data4;
	size = 4;
    } else {
	attr_form = DW_FORM_data8;
	size = 8;
    }

    new_attr = (Dwarf_P_Attribute)
	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = attr_form;
    new_attr->ar_rel_type = R_MIPS_NONE;
    new_attr->ar_reloc_len = 0;	/* irrelevant: unused with R_MIPS_NONE */
    new_attr->ar_nbytes = size;
    new_attr->ar_next = 0;

    new_attr->ar_data = (char *)
	_dwarf_p_get_alloc(dbg, size);
    if (new_attr->ar_data == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    WRITE_UNALIGNED(dbg, new_attr->ar_data,
		    (const void *) &value, sizeof(value), size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Beispiel #14
0
/*
     _dwarf_transform_simplename_to_disk writes 
     ".rel.debug_pubnames",
     ".rel.debug_funcnames",       sgi extension
     ".rel.debug_typenames",       sgi extension
     ".rel.debug_varnames",        sgi extension
     ".rel.debug_weaknames",       sgi extension 
     to disk.
	section_index indexes one of those sections.
	entrykind is one of those 'kind's.

*/
int
_dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg, enum dwarf_sn_kind entrykind, int section_index,	/* in 
													   de_elf_sects 
													   etc 
													 */
				    Dwarf_Error * error)
{


    /* Used to fill in 0. */
    const Dwarf_Signed big_zero = 0;

    /* Used to scan the section data buffers. */
    Dwarf_P_Section_Data debug_sect;

    Dwarf_Signed debug_info_size;

    Dwarf_P_Simple_nameentry nameentry_original;
    Dwarf_P_Simple_nameentry nameentry;
    Dwarf_Small *stream_bytes;
    Dwarf_Small *cur_stream_bytes_ptr;
    Dwarf_Unsigned stream_bytes_count;
    Dwarf_Unsigned adjusted_length;	/* count excluding length field 
					 */


    int uword_size = dbg->de_offset_size;
    int extension_size = dbg->de_64bit_extension ? 4 : 0;

    Dwarf_P_Simple_name_header hdr;


    /* ***** BEGIN CODE ***** */

    debug_info_size = 0;
    for (debug_sect = dbg->de_debug_sects; debug_sect != NULL;
	 debug_sect = debug_sect->ds_next) {
	/* We want the size of the .debug_info section for this CU
	   because the dwarf spec requires us to output it below so we
	   look for it specifically. */
	if (debug_sect->ds_elf_sect_no == dbg->de_elf_sects[DEBUG_INFO]) {
	    debug_info_size += debug_sect->ds_nbytes;
	}
    }

    hdr = &dbg->de_simple_name_headers[entrykind];
    /* Size of the .debug_typenames (or similar) section header. */
    stream_bytes_count = extension_size + uword_size +	/* Size of
							   length
							   field. */
	sizeof(Dwarf_Half) +	/* Size of version field. */
	uword_size +		/* Size of .debug_info offset. */
	uword_size;		/* Size of .debug_names. */



    nameentry_original = hdr->sn_head;
    nameentry = nameentry_original;
    /* add in the content size */
    stream_bytes_count += hdr->sn_net_len;

    /* Size of the last 0 offset. */
    stream_bytes_count += uword_size;

    /* Now we know how long the entire section is */
    GET_CHUNK(dbg, dbg->de_elf_sects[section_index],
	      stream_bytes, (unsigned long) stream_bytes_count, error);
    if (stream_bytes == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (0);
    }
    cur_stream_bytes_ptr = stream_bytes;

    if (extension_size) {
	Dwarf_Unsigned x = DISTINGUISHED_VALUE;

	WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
			(const void *) &x, sizeof(x), extension_size);
	cur_stream_bytes_ptr += extension_size;

    }
    /* Write the adjusted length of .debug_*names section. */
    adjusted_length = stream_bytes_count - uword_size - extension_size;
    WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
		    (const void *) &adjusted_length,
		    sizeof(adjusted_length), uword_size);
    cur_stream_bytes_ptr += uword_size;

    /* Write the version as 2 bytes. */
    {
	Dwarf_Half verstamp = CURRENT_VERSION_STAMP;

	WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
			(const void *) &verstamp,
			sizeof(verstamp), sizeof(Dwarf_Half));
	cur_stream_bytes_ptr += sizeof(Dwarf_Half);
    }

    /* Write the offset of the compile-unit. */
    WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
		    (const void *) &big_zero,
		    sizeof(big_zero), uword_size);
    cur_stream_bytes_ptr += uword_size;

    /* now create the relocation for the compile_unit offset */
    {
	int res = dbg->de_reloc_name(dbg,
				     section_index,
				     extension_size + uword_size +
				     sizeof(Dwarf_Half)
				     /* r_offset */
				     ,
				     /* debug_info section name symbol */
				     dbg->de_sect_name_idx[DEBUG_INFO],
				     dwarf_drt_data_reloc,
				     uword_size);

	if (res != DW_DLV_OK) {
	    {
		_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
		return (0);
	    }
	}
    }

    /* Write the size of .debug_info section. */
    WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
		    (const void *) &debug_info_size,
		    sizeof(debug_info_size), uword_size);
    cur_stream_bytes_ptr += uword_size;


    for (nameentry = nameentry_original;
	 nameentry != NULL; nameentry = nameentry->sne_next) {

	/* Copy offset of die from start of compile-unit. */
	WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
			(const void *) &nameentry->sne_die->di_offset,
			sizeof(nameentry->sne_die->di_offset),
			uword_size);
	cur_stream_bytes_ptr += uword_size;

	/* Copy the type name. */
	strcpy((char *) cur_stream_bytes_ptr, nameentry->sne_name);
	cur_stream_bytes_ptr += nameentry->sne_name_len + 1;
    }

    WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
		    (const void *) &big_zero,
		    sizeof(big_zero), uword_size);




    return (int) dbg->de_n_debug_sect;
}
Beispiel #15
0
/*  This function adds attributes whose value
    is an signed constant.  It determines the
    size of the value field from the value of
    the constant.  */
Dwarf_P_Attribute
dwarf_add_AT_signed_const(Dwarf_P_Debug dbg,
    Dwarf_P_Die ownerdie,
    Dwarf_Half attr,
    Dwarf_Signed value, Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr = 0;
    Dwarf_Half attr_form = 0;
    Dwarf_Small size = 0;

    if (dbg == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (ownerdie == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    switch (attr) {
    case DW_AT_lower_bound:
    case DW_AT_upper_bound:
    case DW_AT_const_value:
    case DW_AT_bit_offset:
    case DW_AT_bit_size:
    case DW_AT_byte_size:
    case DW_AT_count:
    case DW_AT_byte_stride:
    case DW_AT_bit_stride:
    case DW_AT_allocated:
    case DW_AT_associated:
        break;

    default:
        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
            return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
        }
        break;
    }

    /* Compute the number of bytes needed to hold constant. */
    if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
        attr_form = DW_FORM_data1;
        size = 1;
    } else if (value >= SHRT_MIN && value <= SHRT_MAX) {
        attr_form = DW_FORM_data2;
        size = 2;
    } else if (value >= INT_MIN && value <= INT_MAX) {
        attr_form = DW_FORM_data4;
        size = 4;
    } else {
        attr_form = DW_FORM_data8;
        size = 8;
    }

    new_attr = (Dwarf_P_Attribute)
        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = attr_form;
    new_attr->ar_rel_type = R_MIPS_NONE;
    new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
    new_attr->ar_nbytes = size;
    new_attr->ar_next = 0;

    new_attr->ar_data = (char *)
        _dwarf_p_get_alloc(dbg, size);
    if (new_attr->ar_data == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    WRITE_UNALIGNED(dbg, new_attr->ar_data,
        (const void *) &value, sizeof(value), size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Beispiel #16
0
/*  Returns DW_DLV_OK if it works, else DW_DLV_ERROR.
    The caller may decide to ignore the errors or report them. */
static int
update_entry(Dwarf_Debug dbg,
    Dwarf_Bool is_64bit, Dwarf_Endianness endianess,
    Dwarf_Half machine, struct Dwarf_Elf_Rela *rela,
    Dwarf_Small *target_section,
    Dwarf_Small *symtab_section_data,
    Dwarf_Unsigned symtab_section_size,
    Dwarf_Unsigned symtab_section_entrysize,
    int *error)
{
    unsigned int type = 0;
    unsigned int sym_idx = 0;
#ifdef HAVE_ELF64_SYM
    Elf64_Sym sym_buf;
    Elf64_Sym *sym = 0;
#else
    Elf32_Sym sym_buf;
    Elf32_Sym *sym = 0;
#endif
    Elf32_Sym *sym32 = 0;
    Dwarf_ufixed64 offset = 0;
    Dwarf_sfixed64 addend = 0;
    Dwarf_Unsigned reloc_size = 0;
    Dwarf_Unsigned symtab_entry_count = 0;

    if (symtab_section_entrysize == 0) {
        *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
        return DW_DLV_ERROR;
    }
    symtab_entry_count = symtab_section_size/symtab_section_entrysize;

    /* Dwarf_Elf_Rela dereferencing */
    offset = rela->r_offset;
    addend = rela->r_addend;
    type = rela->r_type;
    sym_idx = rela->r_symidx;
    if (sym_idx >= symtab_entry_count) {
        *error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD;
        return DW_DLV_ERROR;
    }



    if (is_64bit) {
#ifdef HAVE_ELF64_SYM
        sym = &((Elf64_Sym*)symtab_section_data)[sym_idx];
#endif
    } else {
        sym32 = &((Elf32_Sym*)symtab_section_data)[sym_idx];

        /*  Convert Elf32_Sym struct to Elf64_Sym struct. We point at
            an Elf64_Sym local variable (sym_buf) to allow us to use the
            same pointer (sym) for both 32-bit and 64-bit instances.  */
        sym = &sym_buf;
        sym->st_name = sym32->st_name;
        sym->st_info = sym32->st_info;
        sym->st_other = sym32->st_other;
        sym->st_shndx = sym32->st_shndx;
        sym->st_value = sym32->st_value;
        sym->st_size = sym32->st_size;
    }

    /* Determine relocation size */
    if (is_32bit_abs_reloc(type, machine)) {
        reloc_size = 4;
    } else if (is_64bit_abs_reloc(type, machine)) {
        reloc_size = 8;
    } else {
        *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
        return DW_DLV_ERROR;
    }


    {
        /*  Assuming we do not need to do a READ_UNALIGNED here
            at target_section + offset and add its value to
            outval.  Some ABIs say no read (for example MIPS),
            but if some do then which ones? */
        Dwarf_Unsigned outval = sym->st_value + addend;
        WRITE_UNALIGNED(dbg,target_section + offset,
            &outval,sizeof(outval),reloc_size);
    }
    return DW_DLV_OK;
}